以前も試してみたtsubakiさんの記事のスクロールビューを使って、銃器切り替えのようなUI部品を製作中です
tsubakit1.hateblo.jp
手順がすごいややこしいので、exportしてしっかり部品化したいと思います。
久しぶりにやったらはまりました(´・ω・`)
まず、
①Canvasの下にemptyを作ってScrollViewの改名
②Mask,Image,ScrollRectをアタッチ
③その下にemptyを作ってContentに改名
④HorizontalLayoutGroup、ScrollController、ContentSizeFilterをアタッチします
横スクロール型なので、HorizonFitをPreferredSizeにします。
(こいつらはcomponent>layoutの中にいます。UIの中にあるかと勘違いした)
⑤ScrollViewのInstanceのContentに、さっき改名したContentをドロップします
(viewするのはこの人ね、的な登録と思う)
⑥ScrollController.csをScrollViewにアタッチ(後述)
横スクロール型のビューに表示されるノードを作ります。
今回はFPS銃器切り替えなので、プレイヤーが保持する銃アイテムのベースになります。
Tsubakiさんの例では、Imageの下にImage、Text、Checkmarkがぶら下がる構成ですが、
今回は、Imageの下にButtonを起きます。クリッカブルにしたいので。button自体で画像とテキストも出せますし。
直接Buttonをノードにしようと思いましたがうまく行きませんでした(研究の余地あり)
このノードには、LayoutElementをアタッチします。これがノードのサイズを意味するので、自動レイアウトが働くようです。
これをアタッチしないとノードが重なってレイアウトされません。
今回は、横スクロールなので、MinWidthを100にしました。
ノードはPrefabに入れておきます。
実行画面は以下のような感じです。AssetStoreからダウンロードしたアイコンを使ってますが、ノードはコードで15個登録しているので、Cloneが15できています。
ノードはボタンなのでクリックするとOnClickが発生します。イベントはListenerを登録して受け取ってDebug.Logで番号を表示しています。
ここで、プレイヤーの銃器を切りかえる処理をすればOKです(まだ作ってませんが)
ノードを動的に登録し、ノードをクリックした場合のイベントも受信するのがScrollControllerです。
Prefabには先程作ったノードをドロップして登録します。
ノードの画像はmultipleで切断されているスプライトです。LoadAllで配列として読み込めます。
ノードを動的生成し、このコードが動いているScrollContorllerの子供として登録
まずノードの子要素のボタンを探して、画像ボタンなので画像を書き換えます。ここで銃器の名称も書き換えると良いでしょう。
次に、イベントリスナーを登録します。私はUIからOnClickを登録する作業がすごく嫌いで面倒くさいです。
コードでやってしまいたい。
AddListenerでコールバック関数を登録しますが、ボタンを区別するために引数iを渡したいところですが、これがなかなか動きません。
ラムダ式というやつで、ローカル変数を経由すると渡せました。(以前は定数を使って、AddListenerを並べてました。クイズアプリとか)
こちらが非常に参考になりました。ありがとうございました。
naochang | 動的にボタンにデータを持った機能を加える
using UnityEngine; using System.Collections; using UnityEngine.UI; public class ScrollController : MonoBehaviour { [SerializeField] RectTransform prefab = null; void Start () { Sprite[] sp = Resources.LoadAll<Sprite>("GUNS"); for (int i = 0; i < 15; i++) { var item = GameObject.Instantiate(prefab) as RectTransform; item.SetParent(transform, false); GameObject bt = item.transform.FindChild("Button").gameObject; Image img = bt.GetComponentInChildren<Image>(); img.sprite = sp[i]; Text txt = bt.transform.FindChild("Text").gameObject.GetComponent<Text>(); txt.text = "Gun " + i; Button bt2 = bt.GetComponent<Button>(); int j = i; bt2.onClick.AddListener(() => { onButtonClick(j); }); } } void onButtonClick(int no) { Debug.Log("Button Click: " + no); } }