uGUIのScrollViewを使いこなす7つのTips
この記事は Unity Advent Calendar 2016 3日目の記事です
Unityは2つとも満員で、さすがに盛り上がってますねー。自分は普段縁がないようなWeb系やサーバーサイドのアドカレをぼんやり眺めるのが好きです。同じプログラミングでもかなり世界が違うものだなと感嘆します。
さてさて、Unity5.2で追加されたuGUIのScrollView。様々な手順が簡略化され、実用的になっていますが、そのままでは若干痒い所に手が届かないところがあります。ここでは、それらを解決する案を紹介しようと思います。
基本的な使い方
その前に、まずは簡単な使い方をおさらいしましょう。
Create > UI > ScrollViewを選択します。
すると
このようなものが生成されます。
ここでは縦のスクロールビューを作ることにしましょう。
その場合、ContentにVertical Layout Group
とContent Size Fitter
をアタッチし、Content Size Fitter
のVertical Fit
をPreferred Size
にします。
そして、ButtonなどのアイテムをContent
の子供に配置し、Layout Element
をアタッチしてMin Height
に適当な値を入れ、好きなだけ複製すると動くようになります。これ以前に比べるとだいぶ簡単になりました。
横スクロールの場合は、Horizontal Layout Group
、1行に複数のアイテムを持たせたい場合はGrid Layout Group
にします。
それでは、Tipsをご覧いただきます。
1. アイテムはプレハブ化する
Content
以下に配置するアイテムが似ている場合はプレハブ化しましょう。
こうすることで、同じ変更を簡単にすべてのアイテムに反映させることができます。
2. アイテムの子供への参照は持たず、それぞれのアイテムが持ちそのアイテムへの参照を持つ
スクリプト操作の話です。 大本のスクリプトからアイテムの子供のそれぞれのオブジェクトを直接参照するよりも、アイテムの親に別のスクリプトをつけてそこへの参照を持ちましょう。
そしてそのスクリプトから各々の子供のオブジェクトを参照することで、アイテムが増減しても変更箇所が1か所で済みます。
スクリプトはこんな感じになるでしょうか。
// Item.cs側 public void SetInformation(string header, string title, string duration) { this.header.text = header; this.title.text = title; this.duration.text = duration; } // ItemManager.cs側 void Start () { for (int i = 0; i < items.Count; i++) { items[i].SetInformation("", "", ""); } }
これはScrollView
に限らずUnity全般同じことが言えます。
3. スクロールバーを消したい場合、ScrollRectのスクロールバーを削除する
縦横どちらかにしかスクロールしない場合、もう片方のスクロールバーは不要になることがほとんどです。Scroll Rect
のスクロールバーのVisiblity
にAuto Hide
系を設定していれば実行時に自動的に消えてくれますが、編集時にもいらないという場合、Scroll Rect
コンポーネント内のHorizontal Scrollbar
を選択してShift+Delで削除してしまいましょう。実体のほうも消して大丈夫です。
ちなみに、標準のScrollbar
でもwidthを10、色を黒、透明度を0.7くらいにすると素材を変えなくてもそこそこ見栄えがいい感じです。
4. スクロールビューのクリップ範囲を変えたいときの方策
ScrollView
はそのままだとImage
目一杯の範囲でクリップされてしまうので、例えば背景画像のふちに装飾がある場合など、端っこより前でクリップしたいことが多くあります。
これに対する解決策は2つ考えられます。
まず、ViewPort
のScaleを0.95くらいにする方法。
手軽ですが、中のオブジェクトもすべてそのスケールになるので場合によっては注意が必要です。
もう一つは、背景画像とScrollView
を分割し、親子関係にする方法。こちらのほうが柔軟性は高いかもしれません。
5. 上下を残したい場合、LayoutGroupのTopやBottomの数値を上げる
↑とも関連がありますが、背景画像に装飾がある場合など、端までスクロールさせたときに最後のアイテムのスクロールの限界を中央寄りにしたい時があります。
その場合、Vertical Layout Group
のPadding
の項目を開き、Bottom
に20などの値を入れてみてください。そうすると、その数値分だけ領域が広がり、余分にスクロールさせることができます。
Horizontal Layout Group
、Grid Layout Group
でも同じ設定があります。
6. スクロールの両端をフェードさせる方法
さて、ここまででクリッピングも正常になり余白も残せましたが、切れ目がはっきり出ているのが気になるかもしれません。そこで、
このようにする方法を紹介します。
やり方としては、上にシェーダーでフェードさせた背景と同じ画像を2回描画します。
いろいろやり方を探りましたが、これが一番簡単で汎用性が高い気がします。(Raycast Targetを外すのを忘れずに)
fragmentシェーダーの部分だけ書くとこんな感じです。
fixed4 c = tex2D(_MainTex, IN.texcoord) * IN.color; c.a *= lerp(0, 1, (IN.texcoord.y - _Start) / (_End - _Start)); return c;
いたってシンプル。
一応、それぞれ別のマテリアルになり、ドローコールを3使う方法なのでモバイルでは注意。
7. スクリプトからなめらかにスクロールさせる
scrollRect.verticalNormalizedPosition
がスクロールの位置になっているので、この数値をいじることでスクリプトからスクロールができます。
ただし、この数値は下端が0、上端が1になっているので注意。
さらに、Mathf.Lerp()
を使うと滑らかに動かせるでしょう。
// 例えばこんな風に void Update () { if (scrollRect.verticalNormalizedPosition != targetPosition) { scrollRect.verticalNormalizedPosition = Mathf.Lerp(scrollRect.verticalNormalizedPosition, targetPosition, 0.16f); } }
まとめ
ここまでを実装したものをGithubにあげました。
スクロールの可否を動的に決定するDynamicScrollable.cs
もおまけで付けてあります。
というわけで、簡単に実装できるScrollViewも工夫すればさらに実用性が高まります。
慣性でスクロール中に端に到達したとき、バウンスバックせずにピタッと止まってしまうのが難点ですが、それ以外はいい感じです。
NGUIではバウンスバックするので、より高度なUIを作るときはいまでもNGUIが人気の理由でしょうか。
逆に言うとそれほど凝らなければuGUIで十分ということでもあります。
あなたは、ScrollViewをどのようにつかっていますか? 何か面白いアイデアがあれば教えてください。( ´∀`)
Have a nice ScrollView!
4日目はhecomiさんです。よろしくお願いします。
参考リンク
UnityのuGUIでスクロールビューを作る (Unity4.6~5.1で必要だった方法)
UnityのuGUIで無限にスクロール出来るスクロールビューを作る
最後に宣伝
ほかにもいくつかUnityネタがあるのですが、Unityが満員なのでさいたまげーむす Advent Calendar 2016に投稿していきます。