ExcelのデータをUnityで読み込んでみた（応用）

2022.4.15　3日目　最近眠いです。この記事は自分が理解する用になってしまっています。めちゃくちゃ省いてしまっています… 

## ExcelのデータをUnityで読み込む（応用）
今日は昨日の復習もかねて、<b>Excelのデータを読み込んで、そのデータ分UIを表示する</b>　というものを実装していきたいと思います。

### 1,Excelの作成

今回は下の画像のようなExcelを作成しました。（英語で書いているのは、フォントにひらがな表記ができるものが無かったためです:( ）
![bandicam 2022-04-15 15-01-24-124.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1940156/12726cdd-32cb-7094-5f20-9869f608e256.jpeg)

作成するものの詳細としては、<b>flagがTRUEのミッションのみScrollViewに表示し、ID2のミッションをクリアしたらID3のミッションを表示できるようにする</b>、です。

### 2,Excelの読み込み
https://qiita.com/amam0102/items/3d0968d2df76f2832f38
↑昨日実装したExcelの読み込みと同じ場所まで実装していきます。

手順を簡単にまとめると、
　　1、ExcelImporterをダウンロード（https://github.com/tsubaki/Unity-Excel-Importer-Maker）
　　　Terasurwareフォルダをプロジェクト内に入れる
　　2、Excelを拡張子「.xls」で作成する
　　3、右クリックしてXLS Import Settings...を選択し、Excelの設定をする（型名等）
　　4、スクリプトを編集してExcelを読み込む
といった流れでしょうか？（手順足りなかったらすみません）

今回はPrefabの機能も使用したので、メモ程度に作成方法から記載していこうかと思います。
### 3,Prefabの作成
（画像てきとうで申し訳ありません）
下の画像のように、Prefab化したいオブジェクトを作成したら、HierarchyからProjectのAsset内に入れることで自動でPrefab化してくれます。（便利✨）
![bandicam 2022-04-15 15-17-21-373.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1940156/202ec997-54b1-53b2-ddd1-59d1c63b013c.jpeg)

今回使用したPrefabは以下の画像のような構成になっております。
（MissionBarオブジェクトにスクリプトをアタッチしています）
![bandicam 2022-04-15 15-23-05-278.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1940156/4f7dfbc3-697d-df35-d489-ba1f878c5873.jpeg)

### 4,Prefabの生成をする

全体を管理する空のオブジェクトを作成し、それに以下のスクリプトをアタッチします。
![bandicam 2022-04-15 15-25-40-727.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1940156/164c1775-9577-8f26-5d72-c7c5329f03d4.jpeg)

```C#:ImportExcelData2
[SerializeField] public GameObject missionBar;
[SerializeField] public GameObject content;
[SerializeField] public int missionNum;
```
![bandicam 2022-04-15 15-38-45-947.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1940156/eca598b0-01a7-beaa-ea5f-ce3d3283d8b8.jpeg)
missionBarはPrefabを、contentはPrefabを生成する際に親とするオブジェクトを入れてます。
missionNumはExcelに記載したミッションの数を入れています。今回は4つなのでInspectorで4と入れています。
（今見返すと変数名やばいですね＞＜）
（なんかGameObjectだとどんなオブジェクトでも入れる事が可能らしく、あまりお勧めできないらしいですね…よくわからないですが。まあまだ理解しなくてもよさそう）


```C#
private StudyExcelData excelData;
```
```
excelData = Resources.Load( "StudyExcelData" ) as StudyExcelData;
```
この2行でExcelデータを取得しています。



```C#
for( int i = 0; i < missionNum ; i++ ) {
    if( excelData.sheets[ 0 ].list[ i ].flag ) {
       GameObject instance = Instantiate( missionBar );
       instance.transform.parent = content.transform;
       instance.GetComponent<MissionBar>( ).setMissionId( i );
    }
}
```
このfor文で、Excelデータ内のリストを読み込み、flagの列の値がTrueだったら、Prefabを生成、さらにPrefabに生成したミッションIDを渡しています。

次は、今回設定したミッションがクリックしたら～なので、クリック用のボタンを設定して、クリックしたら1ずつカウントを増やしていきます。
### 5, クリックボタンの配置と設定
ミッション用のクリックボタンは以下のように設定しました。
![bandicam 2022-04-15 16-41-26-842.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1940156/169dec4e-5fa1-cdd2-7bf1-ab4fbc90ed0e.jpeg)

クリックボタンにアタッチしたスクリプトは以下の通りです。
```C#:ClickButton.cs
using UnityEngine;
using TMPro;

public class ClickButton: MonoBehaviour {

    [SerializeField] public TextMeshProUGUI countText;

    private int clickCount;

    // Start is called before the first frame update
    void Start( ) {
        clickCount = 0;
    }

    // Update is called once per frame
    void Update( ) {
        countText.GetComponent<TextMeshProUGUI>( ).text = clickCount.ToString( );
    }

    public void OnClickButton( ) {
        clickCount++;
    }

    public int getClickcount( ) {
        return clickCount;
    }
}
```

以下の2つの関数で、クリックしたらカウントを増やす、別のクラスでクリックしたカウントを受け取れるようにする、ということをしています。
```C#
public void OnClickButton( ) {
    clickCount++;
}

public int getClickcount( ) {
    return clickCount;
}
```


### 6,クリックした回数によってミッションのステータステキストを更新する
MissionBar.csを更新しました。

```C#:MissionBar.cs
public class MissionBar: MonoBehaviour {

    [SerializeField] public TextMeshProUGUI missionNameText;
    [SerializeField] public TextMeshProUGUI missionStatusText;

    private int _missionID;
    private int _clickCount;
    private bool _clearFlag;
    private StudyExcelData _excelData;
    private GameObject _clickButton;

    // Start is called before the first frame update
    void Start( ) {
        _clearFlag = false;
        _clickButton = GameObject.Find( "ClickButton" );
        _excelData = Resources.Load( "StudyExcelData" ) as StudyExcelData;
        //ミッションテキストの変更
        missionNameText.GetComponent<TextMeshProUGUI>( ).text = _excelData.sheets[ 0 ].list[ _missionID ].mission;
        missionStatusText.GetComponent<TextMeshProUGUI>( ).text = "Challenge";
    }

    // Update is called once per frame
    void Update( ) {
        _clickCount = _clickButton.GetComponent<ClickButton>( ).getClickcount( );
        if( _clickCount >= _excelData.sheets[ 0 ].list[ _missionID ].value && _clearFlag == false ) {
            missionStatusText.GetComponent<TextMeshProUGUI>( ).text = "Clear!!";
            GameObject.Find( "ScrollViewManager" ).GetComponent<ImportExcelData2>( ).missionActive( _missionID );
            _clearFlag = true;
        }
    }

    public void setMissionId( int number ) {
        _missionID = number;
    }
}
```

### 7,非表示にしていたミッションを表示する
```C#:ImportExcelData2
public class ImportExcelData2: MonoBehaviour {

    [SerializeField] public int missionNum;
    [SerializeField] public GameObject missionBar;
    [SerializeField] public GameObject content;

    private StudyExcelData _excelData;
    //生成するミッションバーを配列に格納する
    private GameObject[ ] instance;

    // Start is called before the first frame update
    void Start( ) {
        _excelData = Resources.Load( "StudyExcelData" ) as StudyExcelData;
        instance = new GameObject[ missionNum ];
        for( int i = 0; i < missionNum ; i++ ) {
            if( _excelData.sheets[ 0 ].list[ i ].flag ) {
                instance[ i ] = Instantiate( missionBar );
                instance[ i ].transform.parent = content.transform;
                instance[ i ].GetComponent<MissionBar>( ).setMissionId( i );
            }
        }
    }

    // Update is called once per frame
    void Update( ) {
       
    }

    //ミッションのバーを表示
    public void missionActive( int number ) {
        switch( number ) {
            case 1:
            instance[ 2 ] = Instantiate( missionBar );
            instance[ 2 ].transform.parent = content.transform;
            instance[ 2 ].GetComponent<MissionBar>( ).setMissionId( 2 );
            break;
            case 2:
            instance[ 3 ] = Instantiate( missionBar );
            instance[ 3 ].transform.parent = content.transform;
            instance[ 3 ].GetComponent<MissionBar>( ).setMissionId( 3 );
            break;
            case 3:
            break;
            default:
            break;
        }
    }
}
```

コード内に説明を記載しました。

これで下のような動作ができました。（画質が…）
<img width=600 alt="ダウンロード.gif" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1940156/7fc7f7de-fa71-8c2e-ec87-48ec05e2d68d.gif">

後でもう少しちゃんと書きたいですね。色々省きました。