ゲーム化!tomo_manaのブログ

ゲーム化!tomo-manaのブログ

Unityでゲームを作る方法について紹介しています

Unity学習#14-1 (Unity 2019.4.1f1) リストの基本

Unity学習#14では、リストの要素数でサイズが変わるリストの作成手順について書きました。この記事は、その前段として、リストの作成方法についてまとめたものです。リストには Scroll View を使用します。

先にリストの作成に必要な手順をまとめ、その後に各パラメータについてまとめます。

リストの追加(Scroll View)

リストを追加するために、Hierarchyウィンドウから Scroll View を追加します。
1) Hierarchyウィンドウで右クリック → Create > UI > Scroll View を選択

Scroll View が Canvas の下に追加されます。

f:id:tomo_mana:20200901233224p:plain
Scroll View 追加時(Hierarchyウィンドウ)

Canvas を始めて追加する場合、Event System が一緒に追加されます。Event System は 第13回で簡単に触れています。

Scroll View には、Viewport、Horizontal Scrollbar、Vertical Scrollbar が含まれます。Viewport には、子オブジェクトとしてContent が含まれます。後述しますが、Scroll View に含まれる Scroll Rect コンポーネント、Viewport、Content がリストの基本要素になります。特にリストの要素は Content の下にぶら下げます。

リストの子要素の追加(Panel)

リストの子要素には、Panelを使用します。
1) Hierarchyウィンドウから、先ほど作成した Scroll View の下にあるContent(Scroll View → Viewport → Content)を選択
2) 右クリックして、Create > UI > Panel を選択

f:id:tomo_mana:20200901233603p:plain
リスト子要素(Panel)追加(Hierarchyウィンドウ)

ここでは、縦に要素が並ぶリストについて記します。

リストの子要素の高さ

(Panel の Inspectorウィンドウ上で)Rect Transform の Height に高さを設定します。
(ここではテストとして100)

リストの子要素の配置方法

(Panel の Inspectorウィンドウ上で)Rect Transform の Anchor Preset を left/top にします。

リストの子要素のマージン

リストの子要素にマージンを設定したい場合は、先ほど Content の下に追加した Panel に Layout Element コンポーネントを追加します。
先ほどのContentの下に追加したPanel に Layout Element を追加します。

1) Hierarchyウィンドウから、先ほど作成した Panel を選択( Scroll View → Viewport → Content → Panel )
2) Inspectorウィンドウから、Add Component > Layout > Layout Element を選択

追加された Layout Element コンポーネントに対して、
3) Preferred Height にチェックを付け、高さを設定します。
(デフォルトでは Height と同じ高さになります。後述する Content Size Fitter で使用します)

⇒ 設定しても変わらない!(調査中)

リストの子要素の複製

リストの要素を増やすには、先ほど作成した Panel をクローンします。
1) Hierarchyウィンドウから、Panel を右クリック > Copy
2) Hierarchyウィンドウで Content を選択して右クリック > Paste

必要な数だけ Copy & Paste を繰り返します。

f:id:tomo_mana:20200901234106p:plain
リスト子要素(Panel)追加(Hierarchyウィンドウ)

リストの子要素の整列(Contentへの設定)

リストの要素が少ない(10-20程度)場合は、子要素を自動で整列させるのが便利です。
(リストが多い(数百~数千)場合はメモリを節約するため、表示する部分だけリストの子要素を作る方法もあります。そのうちに挑戦したいと思います。)

子要素の整列 (Vertical Rayout Group)

子要素を縦に整列させたい場合、Content に Vertical Rayout Group を追加します。
(Content 下にリストの要素がぶら下がるため、整列機能も Content に付加します)

1) Hierarchyウィンドウから、Content を選択( Scroll View > Viewport > Content )
2) Inspectorウィンドウで、Add Component > Layout > Vertical Layout Group を追加
3) Inspectorウィンドウで、Rect Transform の Anchor Preset を top/left にします。

子要素の行間を詰める (Content Size Fitter)

Vertical Rayout Group を適用すると、リストの子要素が縦に整列します。
この時、Content の全長に対して均一に要素が並びます。

この隙間を詰めるために、Content Size Fitter を追加します。

1) Hierarchyウィンドウから、Content を選択( Scroll View > Viewport > Content )
2) Inspectorで、Add Component > Layout > Content Size Fitter を追加

Content Size Fitter を追加すると、Content の Rect Transform に、"Some values driven by ContentSizeFitter." が表示されます。(要素数に応じて、Content の全長を自動で調節する)

※Content Size Fitter を設定した後は、Content の Rect Transform の一部が設定しづらくなるようでした。
ある程度子要素の配置が決まってから、Content Size Fitter を適用するのが良さそうです。
(Content Size Fitter 適用後は、Content Size Fitter を削除しても、制限が一部解除されないような気がします)

f:id:tomo_mana:20200901234600p:plain
Contentへの Component の追加(Vertical Layout Group、Content Size Fitter)

リストを構成する要素について

ここからは、リストを構成する各要素について、分かった範囲でまとめます。

Rect Transform

リストの子要素として使用した Panel の位置は、Scroll View と Content の設定で決まります。これは、リストを構成する Scroll View、Viewport、Content それぞれの Rect Transform が関係しています。

Rect Transform は、UI 以外で使われている Transform を継承したもので、表示位置に親子関係を持たせています。
Transform が持つ親子の概念(階層)については以下の記事にまとめています。
tomo-mana.hatenablog.com


Rect Transform は Transform.Position と同じく、 X, Y, Z 座標を持っていますが、Transform の違いは、Rect Transform が、親となるRect Transformとの関係によって設定できるパラメータが変わることです。親のRect Transformとの関係は Anchor Preset で設定します。

Anchor Preset

Rect Transform は、Anchor Preset で、親のどのあたりに自分が張り付くかを親に対して指定します。
Scroll View を構成するCanvas、Scroll View、Viewport、Content は、それぞれ以下の Anchor Preset を持っています。

Game Object Anchor Preset (Scroll Rect)
Canvas f:id:tomo_mana:20200901235622p:plain
非アクティブ。Rect Transform には、"Some values driven by Canvas."のコメントがあります。Canvasコンポーネントを見ると "Target Display" 欄があります。ここから、Rect Transform が Canvasコンポーネントによって操作されて、画面の大きさになろうとしていると思われます。
Scroll View f:id:tomo_mana:20200901235640p:plain
middle/center。画面を司るCanvas Rect Transform の中心=画面の中心にいます(変更可能です)。
Viewport f:id:tomo_mana:20200901235726p:plain
stretch/stretch。親のRect Transformである Scroll View のサイズに自身を合わせます(実際はScroll View にある Scroll Rect コンポーネントが Viewport を参照しており、自身のスクロールバーを表示する領域を除いた領域を Viewport に使わせています。
Content f:id:tomo_mana:20200902000401p:plain
top/stretch。左右は親である Viewport のサイズと同じ、上辺は Viewport に自身を揃えます。

Viewport は Scroll View の Scroll Bar を除いた大きさと同じで、Content は通常 Viewport より大きくなります。また、Viewport に Mask が付いていて、Content を一部非表示にしています。つまり、Scroll View は、Viewport をマスク情報として使用しながら Content の一部を見せ、スクロールバーの位置に一致する Content を都度読み出す画面、ということになります。Viewport が「見せる場所」という名前になっている理由もこれで分かります。

f:id:tomo_mana:20200901224749p:plain
Scroll Rect の階層

上記から、リストの子要素をどう作るかが見えてきます。

※ちなみに、Anchor Preset は少し癖があり、Anchor Preset は X, Y, Z の設定より前に設定されることを想定していると思われます。Anchor Preset を変更しても、要素の見た目が変わらないのは、Anchor Preset を変更した時に、Rect Transform 自身の X, Y, Z 座標を Anchor Preset が自動で書き換えてしまうためです。そのため、Anchor Preset を変更したことでどんな違いが出ているのかを、最初は直感的に理解できないと感じました。Anchor Preset を設定後、X, Y, Z 座標を手動で元に戻すことで、Anchor Preset がどのように効いたかを確かめることができます。

Panel (リストの子要素としての)

今回はリストの子要素にPanelを使用しました。リストの子要素はPanelでなくても良いのですが、リストの子要素に後から色々追加したりする可能性がある場合は、Panelの使用が望ましいと思われます。

Panel の Rect Transform の Anchor Preset 初期値 は stretch/stretch です。これは Panel が Canvas の直下に配置されるものを想定していて、実際にCanvas直下に置かれた時には、画面全体を覆うようなメニューの下地になることを想定していると思われます。
今回はこれをリストの要素として Content に並べるので、Anchor Preset を 試しに center/middle に変更します。

Vertical Layout Group

Panel をもう一つ作成して、同じ設定にすると、Panel が2枚重なった状態になります。(以下の図では、赤と青のパネルが重なって紫に見えています)

f:id:tomo_mana:20200902000916p:plain
Vertical Layout Group適用前


これを上下に並べるために、Panel の親である Content に、Vertical Layout Group を設定します。

f:id:tomo_mana:20200902000942p:plain
Vertical Layout Group適用後

Vertical Layout Group を設定することで、2つのPanelは親であるContentから操作される対象になり、自動で縦に整列します。2つの Panel の Rect Transform の Pos X、Pos Y に自動で値が入力されます。(ちなみに 2つのPanel の Anchor Preset も top/left に自動的に切り替わります)

Content Size Fitter

あとはPanel をたくさん並べればOKなのですが、単純に並べると、Content のサイズいっぱいに Panel が広がってしまいます。

f:id:tomo_mana:20200902001014p:plain
Content Size Fitter 適用前

この行間を適切に詰めるために、Content Size Fitter を設定します。
Content Size Fitter の Vertical Fit を Minimum size または Preferred Size に変えると、行間が詰まります。

f:id:tomo_mana:20200902001035p:plain
Content Size Fitter 適用後

尚、先述の通り、Content Size FItter を設定すると、Content の Rect Transform の設定の一部がうまく変更できなくなります。(一つのパラメータを変更しようとすると他のパラメータが連動して書き換わってしまう、等)
Content Size Fitter を設定する直前の配置から、子要素を動かせなくなるため、子要素の位置がある程度決まってからContent Size Fitter を適用するのが良さそうです(バグ?)

Layout Element

尚、Panel の Minimum Size と Preferred Size は、デフォルトでは 0 が入っている(スクリプトリファレンス)のですが、この Minimum Size または Preferred Size を変更したい場合は、Panel に Layout Element を追加します。(ただ、設定してみましたがマージンが変わらないので、これはもう少し調査が必要そうです)

(以上)