LoginSignup
1
2

More than 5 years have passed since last update.

シンプルなボタンを動的に生成する

Posted at

UniRXを使ってJSONファイルからデータを引っ張りつつ、
Actionメソッドで各ボタンにイベントを付与するサンプル

CODE: https://github.com/mo49/SimpleButton

ItemApi.cs

APIのラッパークラスを定義

using System.Collections.Generic;
using UnityEngine;
using UniRx;
using System;
using System.IO;

public class ItemApi : MonoBehaviour{

    /// <summary>
    /// ローカルのJSONを返すObservableを返す
    /// </summary>
    public IObservable<List<ItemInfo>> GetItems()
    {
        var path = Application.dataPath + "/info.json";
        StreamReader reader = new StreamReader(path);
        string json = reader.ReadToEnd();

        return ListJsonAs<ItemInfo>(json);
    }

    /// <summary>
    /// JSON配列の処理
    /// https://qiita.com/akira-sasaki/items/71c13374698b821c4d73
    /// </summary>
    private IObservable<List<T>> ListJsonAs<T>(string json)
    {
        Wrapper<T> wrapper = JsonUtility.FromJson<Wrapper<T>>(json);
        return Observable.Return(wrapper.list);
    }

    class Wrapper<T>
    {
        public List<T> list;
    }
}

App.cs

APIのラッパークラスにアクセスしやすくする

public class App {

    public static readonly App Instance = new App();

    // App.Instance.Api でアクセスできるようにする
    public readonly ItemApi Api = new ItemApi();

    private App() {

    }

}

ItemInfo.cs

JSON構造の規定

using System;

/// <summary>
/// JSON構造の規定
/// </summary>
[Serializable]
public class ItemInfo {
    public string key;
    public string name;
    public int sex;
    public bool isRegistered;
}

サンプルのJSON

info.json
{
    "list": [
        {
            "key": "1",
            "name": "Bob",
            "sex": 1,
            "isRegistered": true
        },
        {
            "key": "2",
            "name": "Steve",
            "sex": 1,
            "isRegistered": false
        },
        {
            "key": "3",
            "name": "Carol",
            "sex": 2,
            "isRegistered": false
        }
    ]
}

ItemLoader.cs

JSON取得のAPIをSubscribeし、完了したら通知する

using System.Collections.Generic;
using UnityEngine;
using UniRx;
using System;

public class ItemLoader : MonoBehaviour {

    public GameObject m_Item;

    // 非同期専用のSubject
    private AsyncSubject<List<ItemInfo>> m_ItemInfos = new AsyncSubject<List<ItemInfo>>();
    // Expression-bodied
    public IObservable<List<ItemInfo>> ItemInfos => m_ItemInfos;

    public void Load()
    {
        App.Instance.Api.GetItems().Subscribe(data => {
            m_ItemInfos.OnNext(data);
            m_ItemInfos.OnCompleted();
        });
    }
}

ItemManager.cs

各アイテムを生成し、クリック時に実行させるActionメソッドの中身を定義

using System.Collections.Generic;
using UnityEngine;
using UniRx;

public class ItemManager : MonoBehaviour {

    [SerializeField] GameObject m_Item;

    [SerializeField] Transform m_ItemRoot; 

    [SerializeField] ItemLoader m_ItemLoader;

    void Start () 
    {
        m_ItemLoader.Load();
        m_ItemLoader.ItemInfos.Subscribe(infos => CreateItem(infos));
    }

    void CreateItem(List<ItemInfo> infos) 
    {
        foreach (var info in infos)
        {
            GameObject obj = Instantiate(m_Item, m_ItemRoot);
            Item item = obj.GetComponent<Item>();
            item.Draw(info);
            // アクションイベントの登録(委譲元)
            item.ActionOnClick += val =>
            {
                Debug.Log("clicked: " + val.name);
            };
        }
    }
}

Item.cs

Itemプレファブにアタッチするスクリプト
Itemの情報を描画
Actionメソッドの実行

using UnityEngine;
using UnityEngine.UI;
using System;

public class Item : MonoBehaviour {

    [SerializeField] Button button;
    [SerializeField] Text text;

    private ItemInfo m_ItemInfo;

    // アクションイベントを実行する(委譲先)
    public Action<ItemInfo> ActionOnClick;

    public void Draw(ItemInfo info) 
    {
        m_ItemInfo = info;
        text.text = info.name;
        button.GetComponent<RectTransform>().localPosition = new Vector3(int.Parse(info.key) * 100f, 100f, 0f);
    }

    public void OnClick() 
    {
        ActionOnClick(m_ItemInfo);
    }
}

スクリーンショット 2018-11-12 12.26.15.png

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2