【Unity】 テキストファイルを読み取り、自動でスクロールコンテンツを生成してくれるInfiniteScroll+α

##まずはじめに
　前提として、ある程度Unityの操作に慣れていて、用語がそれなりに分かっている事を前提条件としているため、全くの初心者が読む記事ではありません。

　この記事は、tsubaki様製作の[Infinite Scroll](https://github.com/tsubaki/Unity_UI_Samples)を使用、改変しています。
**【[Ifinite Scrollの使い方が記載されたブログ記事](http://tsubakit1.hateblo.jp/entry/2015/01/21/233000)】**

　このスクリプトがなければ出来なかったです、この場をお借りしてtsubaki様にお礼申し上げます。

##Step1、Inifite ScrollをDLし、LimitedのSceneを開く
- まず初めに[Infinit Scroll](https://github.com/tsubaki/Unity_UI_Samples)をDLする。
![スクリーンショット (11)_LI.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/421073/598c37ff-baa4-447c-0bfe-11e807c369de.jpeg)

- DLが完了したら、ファイルを解凍し、UnityのOpen Projectから解凍したフォルダを選択して開く。
![スクリーンショット (12).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/421073/3938bebe-e621-865f-9401-b58c4a66d6ca.png)
- Projectが開いたら、Infinite Scrollフォルダ内にあるLimitedを開き、ダブルクリックしてシーンを開く。
（左下の警告はバージョンの互換による警告なので無視してよい）
![スクリーンショット (15)_LI.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/421073/8143362b-8e69-4a5c-76fb-1a15348dec54.jpeg)

これでひとまず、シーンを再生すると99個までスクロールできるスクロールが生成されるようになった。

##Step2、文字を読み取るための下準備
- Inifite Scrollはプレハブ化されたベースとなるオブジェクトを量産し、Itemスクリプトによりベースの中身をそれぞれ書き換えることでコンテンツを量産しています。
![スクリーンショット (16)_LI.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/421073/848c08fd-3d38-9fda-be8e-ae8d87e8e7e0.jpeg)

- まずは読み取り先のテキストファイルを作成していきます。ProjectのAseetsフォルダ内にCreateからFolderを選択し、名前を`Resources`とします。
このフォルダの中に、テキストファイルを入れます。テキストファイルはUnityでは作成できないので、メモ帳などの機能を使って作ったものをドラッグ＆ドロップで入れてください。
 ![スクリーンショット (19).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/421073/c771e2d7-4949-e78e-1354-34514e448d38.png)

- テキストファイルの中身は後に改行ごとに切り分けて一行分のデータとして保存されるので、表示する際に二行にしたい場合はHTMLタグの`<br>`をテキストファイル内で記述するとできます。
<br>
- 次にItemスクリプトに代わるスクリプトを作成します、このスクリプトでテキストファイルのデータを読み取り、コンテンツに代入して表示します。
<details><summary>MyItem.cs　（click here) </summary><div>

```C#:MyItem.cs

using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

public class MyItem : UIBehaviour 
{
    [SerializeField]
    Text uiText = null;

    [SerializeField]
    Text MaineText = null;
    static Text mein;

    public string[] textMessage; //テキストの加工前の一行を入れる変数
    public string[,] textWords; //テキストの複数列を入れる2次元配列 

    public static int rowLength; //テキスト内の行数を取得する変数 @staticに変更
    private int columnLength; //テキスト内の列数を取得する変数

    int i; //@外側で宣言
    int n; //@外側で宣言

    new private void Start()
    {
        TextAsset textasset = new TextAsset(); //テキストファイルのデータを取得するインスタンスを作成
        textasset = Resources.Load("Test", typeof(TextAsset) )as TextAsset; //Resourcesフォルダから対象テキストを取得
        string TextLines = textasset.text; //テキスト全体をstring型で入れる変数を用意して入れる

        //Splitで一行づつを代入した1次配列を作成
        textMessage = TextLines.Split('\n'); 

        //行数と列数を取得
        columnLength = textMessage[0].Split('\t').Length;
        rowLength = textMessage.Length;

        //2次配列を定義
        textWords = new string[rowLength, columnLength];

        for( i = 0; i < rowLength; i++)
        {
            string[] tempWords = textMessage[i].Split('\t'); //textMessageをカンマごとに分けたものを一時的にtempWordsに代入

            for ( n = 0; n < columnLength; n++)
            {
                textWords[i, n] = tempWords[n]; //2次配列textWordsにカンマごとに分けたtempWordsを代入していく
            }
        }
    }

    //プレハブ化された表示形式に以下の処理で文字と画像を順番に割り当てていく
    public void UpdateItem(int count) 
    {
        Start();
        n = 0;

        //アイテムナンバー、0から始まるので+1をして1から表記
        uiText.text = (count + 1).ToString("00");

        //テキストの行数を超えないように制限、テキストをカウントに併せて変更。
        if(count < rowLength)
        {
            MaineText.text = (textWords[count, 0]);
        }       
    }
}

```
</div>　</details>



処理内容の解説をすると非常に長くなるので、重要な部分のみ説明します。<br>
`textasset = Resources.Load("Test", typeof(TextAsset) )as TextAsset; `<br>
　この一文がリソースフォルダからテキストファイルを読み取る処理となっています。<br>""で区切られた部分を対応するテキストファイルの名前にすることで、読み取るテキストファイルを変えることができます。<br>
　画像を読み取り＆変更したい場合は元のItemスクリプトを参照してください、Commonフォルダの中にスクリプトがあります。
<br>
 

##Step3、文字を表示するベースオブジェクトの作成
 次に文字を表示するためのベースとなるオブジェクトをHierarchy上で作成し、プレハブ化します。
（hierarchyのオブジェクトをProjectにドラッグ＆ドロップ）<br>

<b>ベースを作成する際の重要な部分</b>ですが、オブジェクトをまとめている親オブジェトのRectTransformが以下の画像のようになっている必要があります。これができていないと、後にシーンを再生してもコンテンツが下の方に生成され、ゲームビュー内に移ら映らないない場合があります。
Heightの部分は子オブジェクトの大きさによって左右されるため、適宜調整してください。
<br>

この時、先ほど作ったスクリプトをGameObject（親）にアタッチし、それぞれのインスペクターに対応したオブジェクトをアタッチします。
プレハブ化が済んだらHierarchyに残っているベースは消します。

![スクリーンショット (24)_LI.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/421073/658c51d6-81a6-dba3-3946-3f3668d31be9.jpeg)


```
Hierarchy
　GameObject（空のオブジェクト）-MyItem.csをアタッチ
　　-Image（背景の白）
　　-NumberText（順に番号が割り振られる、画像の00にあたる）-MyItem.csのUiTextにアタッチ
　　-MaineText（読み取った文字を書き込むテキスト、画像のtestにあたる）-MyItem.csのMaineTextにアタッチ
  ```
このプレハブをInifite Scroll.csのItem Prototypeにドラッグ＆ドロップします。
![スクリーンショット (23)_LI.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/421073/67cf3576-da31-c106-fe31-6bcc41d7bc2a.jpeg)

この状態でシーンを再生しても、まだ量産体制が整っていないので、ただベースのオブジェクトが表示されるだけです。
ScrollContentにアタッチされているItem Controller LimitedスクリプトをRemoveComponentし、代わりに以下のスクリプトをアタッチします。
<details><summary>MyItemControllerLimited.cs　（click here) </summary><div>

```C#:MyItemControllerLimited.cs
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

[RequireComponent(typeof(InfiniteScroll))]
public class MyItemControllerLimited :  UIBehaviour, IInfiniteScrollSetup
{

	[SerializeField, Range(1, 999)]
	private int max = 30;

	public void OnPostSetupItems()
	{
        max = MyItem.rowLength;
		var infiniteScroll = GetComponent<InfiniteScroll>();
		infiniteScroll.onUpdateItem.AddListener(OnUpdateItem);
		GetComponentInParent<ScrollRect>().movementType = ScrollRect.MovementType.Elastic;

		var rectTransform = GetComponent<RectTransform>();
		var delta = rectTransform.sizeDelta;
		delta.y = infiniteScroll.itemScale * max;
		rectTransform.sizeDelta = delta;
	}

	public void OnUpdateItem(int itemCount, GameObject obj)
	{
		if(itemCount < 0 || itemCount >= max) {
			obj.SetActive (false);
		}
		else {
			obj.SetActive (true);
			
			var item = obj.GetComponentInChildren<MyItem>();
			item.UpdateItem(itemCount);
		}
	}
}
```
</div>　</details>

これでシーンを再生すると、文字を読み取ってコンテンツに表記し、自動生成してくれるようになりました。
あとはテキストファイルの中身を変更したり、ベースオブジェクトを変更することで自在に使用できます。

![スクロール作成.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/421073/562f583a-ac0d-f76a-35c3-d9f72c07e59b.gif)

##さいごに
ここまで読んでいただき、ありがとうございました。

おそらくこの記事通りにこなせば、最後のGIF通りの結果となるはずですが、万が一記述漏れなどがあるかもしれないので、うまくいかなかった場合はコメントしてもらえると対応出来るかもしれません。

お疲れ様でした。