【Unity】動的に要素が増える背景画像付きのScroolViewの実装方法

シェアする

Unityでリストの様な物を作る際「ScrollView」を使いますが、大抵の場合、リストの要素は動的に増えていきます。
始めから要素数の決まっているタイプのリストなら良いのですが、そうではない場合は一工夫必要です。

今回は、動的に要素の増えるリストを、ScrollViewを使って実装する方法をご紹介します。

また、ScrollViewには模様付きの背景画像があり、スクロール時に一緒にスクロールして貰おうと思います。

スポンサーリンク

作業環境

  • MacBook Air
  • macOS Sierra 10.12.6
  • Unity 5.5.4p5

画像素材の準備

空想曲線様より。
メッセージ枠を使わせていただいております。

とりあえずインポートしてUIで使えるように設定を変更。

設定が終わったら「Sprite Editor」ボタンを押します。

この様に調整しておきます。
UIが元画像より大きくなった時に、描画をループする部分を囲っています。

ScrollViewの作成

まずはScrollViewを作ります。
今回は縦方向にスクロールする、テキストのリストを作ろうと思います。
作成した「Scroll View」オブジェクトのWidthを、
文字が収まるように適当な値に設定します。
今回は「500」にしました。

続いて、Heightの値を設定します。
このHeightの値は、リストを納めるウィンドウの縦サイズになります。
値を小さくするとウィンドウは狭くなり、必要なスクロール量が増えます。
今回は 「280」に設定しました。

リストに表示するアイテムを作成

今回リストに並べるのは文字なので、「Text」オブジェクトを作成します。
(アイコン等を並べる場合には、「Image」を使います。)
Scroll View」の中の「Content」を右クリックして、UIからTextを選択します。
作成したTextのInspectorからAddComponentボタンで
Layout Element」を追加します。
Layout Element」の「Preferred Width」のチェックボックスをONにしておきます。
値は「30」に設定しました。
FontSizeも見やすい大きさに変更しておきましょう。
合わせて、TextのRectTransformのWidthも
文字列が納まるように適当な値に変更しておきます。

Contentオブジェクトの設定

Scroll View」を開いていき、「Content」を選択します。

AddComponentから、
– Image
– Vertical Layout Group
– Content Size Fitter

を、追加します。

Imageコンポーネントの設定

Imageに先ほど準備した枠の画像を適用します。
「image Type」を忘れずに「Tiled」に設定しておきます。
これで枠が広がった時に、UIの見た目が崩れない様になります。

VerticalLayoutGroupの設定
Paddingの中の、LeftとTopの値を以下の様に変更し、レイアウトを調節します。

  • Left : 200
  • Top : 10
  • Bottom : 10

Child Force Expand」の、Width及びHeightのチェックボックスをOFFにします。
今回は、各アイテムの大きさを自動で拡大する必要は無いためです。

ContentSizeFitterの設定
縦方向で合わせるので、Vertical Fitを「Preferred Size」に変更します。

ScrollViewオブジェクトの設定

最後に、ScrollViewオブジェクトを設定します。
今回は縦方向のスクロールのみなので、「Horizontal」の
チェックボックスを「OFF」にします。
さらに、「Horizontal Scrollbar」を「None」にしておきます。

もし、余剰分のスクロールを制限したい場合は、「Movement Type」を
Clamped」に設定しておきましょう。

ここまで完了したら、Contentの子にある、先ほど作成した「Text」をPrefab化し、
削除しておきます。

リストのテキスト生成用スクリプトの作成

生成時の処理を書いたスクリプトを作成します。
とりあえず動かすだけなので、ボタンにアタッチして使います。


using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class AddSkillButton : MonoBehaviour {

    private GameObject content;
    private GameObject textPrefab;
    private Button getSkillButton;
    private List skillList = new List();

    void Awake(){
        skillList.Add ("料理");
        skillList.Add ("栽培");
        skillList.Add ("鑑定");
        skillList.Add ("園芸");
        skillList.Add ("裁縫");
        skillList.Add ("調合");
        skillList.Add ("整頓");
        skillList.Add ("彫金");
        skillList.Add ("木工");
        skillList.Add ("鍛治");
        skillList.Add ("採掘");
        skillList.Add ("精製");
        skillList.Add ("水泳");
        skillList.Add ("錬金");
        skillList.Add ("合成");
        skillList.Add ("分解");
        skillList.Add ("演奏");
        skillList.Add ("作曲");
        skillList.Add ("歌唱");
        skillList.Add ("休憩");
        Debug.Log (skillList.Count);
        content = GameObject.Find ("Content");
        textPrefab = (GameObject)Resources.Load("Prefabs/Text");
        getSkillButton = transform.GetComponent<button> ();
    }

    void Start(){
        int max = Random.Range(1,skillList.Count - 5);
        Debug.Log (max);
        for(int i = 0; i &lt; max; i++){
            Debug.Log(i);
            GameObject _text = Instantiate (textPrefab, content.transform);
            int index = Random.Range (0, skillList.Count);
            _text.GetComponent ().text = skillList [index];
            skillList.RemoveAt (index);
        }
    }

    public void OnClickAddSkillButton(){
        if (skillList.Count &gt; 0) {
            GameObject _text = Instantiate (textPrefab, content.transform);
            int index = Random.Range (0, skillList.Count);
            _text.GetComponent ().text = skillList [index];
            skillList.RemoveAt (index);
            Debug.Log (skillList.Count);
        } else {
            getSkillButton.interactable = false;
            getSkillButton.GetComponentInChildren ().text = "GetAllSkill!";
            Debug.Log ("GetALLSkill!");
        }
    }
}

string型のListを作り、適当に文字列を登録します。
あとはボタンが押された時に、「Content」の下にTextPrefabを使って
GameObjectを作成し、Textコンポーネントのtextを書き換えています。
使用した文字列は、再度使われない様にListから削除しています。
Listの要素がなくなったら、ボタンを押せないようにし、ボタンの文言も書き換えます。

スクリプトの適用

スクリプトの作成が終わったら、適当な場所に「Button」を作ります。
「Button」オブジェクトに先ほど作成したスクリプトをアタッチし、
Inspectorの「Button」コンポーネントの「OnClick」に
「OnClickAddSkillButton()」を登録します。



シーンを再生すると、ランダムでいくつかのテキストが作成されます。
ボタンを押すことで、リストに残っているテキストが追加され、
全部追加されるとボタンが押せなくなります。
要素数に応じて、ウィンドウ枠が広がること、スクロール時に
背景もスクロールしている事を確認できます。

横スクロールの場合

横方向にスクロールさせたい場合は、「Horizontal Layout Group」を使います。
機能的には同じ様な物なので、適宜横方向スクロールに
置き換えて考えれば問題ないと思います。

サンプルプロジェクト

githubに、今回の実装をしたサンプルプロジェクトがあります。

Contribute to ChatLune/blog-unity-ScrollViewBasic development by creating an account on GitHub.

適宜ご活用ください。

応用的な内容

またの機会になりますが、ScrollViewで作ったリストにHeader要素を追加したり、
リストの最後に要素を付け足したい時などに、
「Layout Group」系コンポーネントを使った時の、
オートレイアウトの落とし穴についてご紹介したいと思います。

入社3年目のエンジニアです。

主にiOS/Androidアプリの開発をしています。

スポンサーリンク

シェアする

フォローする