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

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

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

## ItemApi.cs

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

```csharp
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のラッパークラスにアクセスしやすくする

```csharp
public class App {

    public static readonly App Instance = new App();

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

    private App() {

    }

}
```

## ItemInfo.cs

JSON構造の規定

```csharp
using System;

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

サンプルのJSON

```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し、完了したら通知する

```csharp
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メソッドの中身を定義

```csharp
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メソッドの実行

```csharp
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);
    }
}
```

<img width="506" alt="スクリーンショット 2018-11-12 12.26.15.png" src="https://qiita-image-store.s3.amazonaws.com/0/136286/677d12b5-253d-9563-2a7c-616803e21355.png">