【UE4】BPで二次元配列を作成する

UnrealEngine4を使う上で、二次元配列は鬼門になる事が多いかと思います。
特にブループリントでは、デフォルトで直接宣言する事は出来ない為、やり方を工夫する必要があります。
今回は、どうしてもブループリントで二次元配列の実現が必要であった為、足掻いた事のメモとなります。

# 二次元配列の実装ロジック

ネット上を検索したところ、ブループリントでの二次元配列の実装例はいくつか出て来るかと思いますが、
だいたいは、以下の2パターンになるかと思います。

* 構造体を使う
* 一次元配列のみで実現する
* C++で実装する

# C++での実装では駄目なのか

C++でなら、二次元配列を使用できる為、C++での実装するというのもありだと思います。
しかし、以下のデメリットもあり、扱いに悩みます。

* 変更が必要な場合は、ビルトする必要がある
* エンジニア(C++を扱える人)しかさわれない
* ブループリントで作成した構造体やブループリントを扱えない

これらの事を考えると、ブループリントで手軽に扱いたいという感じも出てきます。


# 構造体を使う

配列を持たせた構造体を用意し、更にそれを構造体にするという物になります。
まめおさんの記事の[こちら](https://papersloth.hatenablog.com/entry/2019/05/31/014956)が参考になります。

# 一次元配列のみで実現する

一次元配列を二次元配列のように使用する方法で、最初に横軸の長さを決めておく必要があります。
例えば、横軸の長さが、10x10の配列を想定して、2列5行目にアクセスしたい場合は、以下の方法で、一次元配列のアクセス先を調べられます。

```
column = 2    // 縦の番号
row = 5       // 横の番号
width = 10    // 横軸の長さ

key = column * width + row  // keyは、一次元配列のアクセス番号
```

※但し、プログラムでの配列は、<font color="Red">**0始まりである事に注意**</font> 

ブループリントで簡単に再現したものが以下の画像となります。
ただ、この方法の場合は、最初に配列の入れ物を先に確保しておく必要があり、その為、InitArrayのような事をやっています。
また、初期に確保した配列の大きさを変更する事も難しく、一度、配列を全てリセットし、必要なサイズを確保し直す必要があります。

全体のブループリント
![スクリーンショット 2021-04-17 210036.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153021/cc29d73f-e9e4-085d-3534-d42ab098b9ca.png)
InitArray
![スクリーンショット 2021-04-17 210126.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153021/fed4887f-9348-0db9-682c-babc55f40e2c.png)
GetKey
![スクリーンショット 2021-04-17 210205.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153021/ace867fc-45d3-6df2-91f6-b6f863535dc8.png)



# 今回のやった事

二次元配列のMapの中に配列を持たせるという構成で使用しました。

# 問題になった事

Mapの中の配列に要素を追加する際に、Addで追加されなかった為、悩みました。
MapをFindで中身を取り出し、その中の配列にAddで追加を行ったところ、要素が追加されません。
![2次元配列に追加する(失敗例).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153021/05f1dd0b-1fe4-5c8f-16e1-8811ed282dd2.png)

#### 入力用のUI
![入力例.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153021/97b00a2d-6bec-907b-0923-dae0424f3321.png)

#### アウトプットの内容
セットボタンで値を配列に追加ていき、追加後に配列の中身をダンプするようにしています。
「Apple」「Orange」には、入力する度に違う値を入れていますが、2番目の要素以降には全く追加されません。
![アウトプットのログ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153021/663d5073-85a5-af88-4689-d0fb86833945.png)

#### 全体のブループリント
[2次元配列に追加する(失敗例)](https://blueprintue.com/blueprint/ql4_ee3u/)



# 解決策(力業)

色々試して、力業で解決した最初の方法です。
やり方としては、単純で新しい要素を追加する際に、Mapの要素を削除して、AddでMapに追加し直すという方法です。
メモリ的には、<font color="Red">**大変優しくない**</font>方法です。。。
![2次元配列に追加する(力技).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153021/3f73d33f-a8f8-c3b0-657d-316f3fc08fc4.png)

#### アウトプットの内容
値が配列に追加されていっています。
![アウトプットのログ(力技).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153021/86771aab-5523-4b6d-d2c8-449bcdc9a017.png)


#### 全体のブループリント
[2次元配列に追加する(力技)](https://blueprintue.com/blueprint/b-78vj3e/)


# 解決策(結論)

色々考えた結果、配列を持ったブループリントを作りました。
ブループリント単体で注目すれば、一次元配列として扱う為、安全かつ分かりやすそうに思えます。

![2次元配列に追加する(ブループリント).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153021/ea8c48b8-7c0c-c613-cef7-ae0cbbb63f09.png)

#### TestBlueprintクラス
![TestBlueprint.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153021/140b0384-7ace-46bf-7fc3-92063542e9db.png)

#### アウトプットの内容
正しく動作しています。
![アウトプットのログ(ブループリント).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153021/daa92156-fa99-dced-420e-09803a777f1a.png)


[2次元配列に追加する(ブループリント)](https://blueprintue.com/blueprint/5b6a27xs/)

# 参考サイト
https://katze.hatenablog.jp/entry/2016/06/25/144111