スマホ向けにステージ選択や、アイテム一覧を作る場合、スクロールへの対応が必須。
Scroll Viewと、標準搭載のコンポーネント、+少しのコードで結構簡単に実装出来る。
横スクロールを想定しているので、縦スクロールにしたい場合は、VerticalとHorizontalを差し替えてください。
なんかモサモサすると思ったら、Scroll Viewを使った手法では重くなる模様。
MaskをRectMask2Dに差し替えると若干緩和するらしい。
↓配列で管理するパターンの、無限スクロール可能ステージセレクトを作りました。
(この記事の物は)↓の自作アプリで実際に使用。
サンプル動画
縦向きなので、ちょっと見辛いかも知れない。
動画下部で画像選択として使用している。
ざっくりとした手順
- Scroll Viewを作成、適切に設定。
- Scroll View下のContentを選択。
- Content Size Fitterをアタッチし、有効化。
- Horizontal Layout Group(横スクロール)か、Vertical Layout Group(縦スクロール)をアタッチし、適切に設定。
- ステージ選択に使うボタンをプレハブ化。
- ゲーム開始時に、ボタンプレハブをInstantiate。
- Contentを親に設定。
- Imageをステージのサムネイルに設定。
- (追加で、Text等でステージナンバーを表示しても良い)
- onClickのリスナーにインデックスを引数にしたメソッドを登録。
詳細な手順
- 上部メニュー -> GameObject -> UI -> Canvasを選択、作成。
- インスペクター -> Canvas Scalerコンポーネントの設定を変更。
- UI Scale Mode:Scale With Screen Sizeに変更。
- Reference Resolution:X 1920、Y 1080等に設定。
- 上部メニュー -> GameObject -> UI -> Scroll Viewを選択、(1)のCanvas下に作成。
- Scroll Viewの設定を変更。
- インスペクター -> Scroll Rectコンポーネント
- Movement Type:Clampedに変更。
- Vertical:無効化。
- インスペクター -> Rect Transformコンポーネント
- Pos:想定するステージセレクト枠の位置に変更。
- Width、Height:想定するステージセレクト枠の大きさに変更。
- ヒエラルキー -> Scroll View -> Scrollbar Verticalを削除。
- インスペクター -> Scroll Rectコンポーネント
- ヒエラルキー -> Scroll View -> Viewport -> Contentを選択。
- Contentの設定を変更。
- インスペクター -> Rect Transformコンポーネント
- Pos Y:(ボタンのHeight – Scrollbar HorizontalのHeigth) * -0.5程に変更。
- インスペクター -> Add Component -> Content Size Fitterを選択、アタッチ。続いて設定。
- Horizontal Fit、Vertical Fit:Preferred Sizeに変更。
- インスペクター -> Add Component -> Horizontal Layout Groupを選択、アタッチ。続いて設定。
- Padding -> Left、Right:スクロール空間の左端、右端に空けるスペースの値を設定(正のInt)
- Spacing:各要素間のマージンの値を設定。
- Child Alignment:Middle Centerに。
- Child Force ExpandのWidth、Heightを無効化。
- インスペクター -> Rect Transformコンポーネント
- GameObject -> UI -> Buttonを選択、作成。
- ボタンの設定を変更。
- インスペクター -> Rect Transformコンポーネント
- Width、Height:任意の大きさに調整(選択出来るような大きさで)。
- ヒエラルキー -> Button下のTextを削除。
- ButtonをProjectウィンドウの任意のフォルダへドラッグ&ドロップしてプレハブ化。
- ヒエラルキー -> Buttonは削除しておく。
- インスペクター -> Rect Transformコンポーネント
コード
以下のコードをUIManager的なスクリプトに記述、もしくは新規作成。
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
//名前はスクリプト名と同じ物に差し替えてください。
public class Test : MonoBehaviour
{
//インスペクターで、ステージセレクトのサムネイル画像を登録。
[SerializeField]
List<Sprite> stageSelectSpriteList = new List<Sprite>();
//インスペクターで、ステージセレクトのボタンのプレハブを登録。
[SerializeField]
GameObject buttonPrefab;
//インスペクターで、Scroll View下のContentを登録。
[SerializeField]
Transform stageSelectContentTransform;
//一時的に使用。
GameObject tempButtonGameObject;
void Awake()
{
//適当に初期化時に呼ぶ。
InitializeStageSelect();
}
void InitializeStageSelect()
{
for (int i = 0; i < stageSelectSpriteList.Count; i++) {
//リスナーの仕様上、こう書く必要がある。
int index = i;
tempButtonGameObject = Instantiate(buttonPrefab, stageSelectContentTransform);
//引数ありのリスナー登録。
tempButtonGameObject.GetComponent<Button>().onClick.AddListener(() => StageSelect(index));
tempButtonGameObject.GetComponent<Image>().sprite = stageSelectSpriteList[i];
}
}
void StageSelect(int index)
{
//ここにIndexに応じたステージセレクト処理を書く(シーンのロードや、難易度の設定等)。
//動作チェック用。インデックスをコンソールへ表示。
print("Touched : " + index);
}
}
- 各ステージのサムネイル画像
- Texture Type:Sprite (2D and UI)に変更。Apply。
- stageSelectSpriteList
- Size:ステージ数と同じ値に設定。
- Sizeの変更で出現したElement:各ステージのサムネイル画像を登録(ステージの順番と一致させる)。
- buttonPrefab
ボタンのプレハブを登録。 - stageSelectContentTransform
ヒエラルキー -> Scroll View下のContentを登録。