例えばテトリスのように、ブロックの Pawn を座標で管理したい場面は多々あります。
それぞれの Pawn 等には座標のパラメーターが存在し、Pawn から座標を参照することはできますが、逆はできません(筆者が知らないだけで、やり方はあるのかもしれない)。
下画像を見てください。黄色いブロックは縦横の座標の目盛りを表し、(0,0) 座標から (4,4) 座標までをグレーのブロックもしくは空間で埋めている図です。
この処理の表示自体は、座標をずらしながら配置していくだけなので簡単ですが、ここから例えば「(0,3) にあるブロックを消す」処理はどうすれば良いでしょうか。
さらに、それだけならまだ何とかなるかも知れませんが、全体を下方向にシフトして各ブロックが新しい座標になった後に「任意の座標のブロックを消す」処理は出来るでしょうか。
このような各座標の位置が固定されている場合に、特定の座標にあるアクタを選択する簡単な方法は、Pawn を配列で管理することです。
まず Pawn 等のアクタを配列で管理する方法を学び、二次元配列での管理へと拡張していきましょう。
1.アクタを配列に追加する
アクタを配列で管理するには、スポーンさせたアクタを配列に追加すれば良いです。下の処理は「Box」という名前の Pawn を Actor 型の BoxActorArray という配列に追加した例です。
これを実行すると、以下のようにインデックス番号が記載されたボックスが3つ現れます。
分かるとは思いますが念のため説明しておくと、ボックスのスポーンは Spawn AIFrom Class だけで完了するので、配列への追加をしなくても同じように表示はされます。あくまで、その後の操作を楽にするために配列に追加するのです。
また、ボックスは立方体のメッシュに TextRender を追加しただけのものです。
2.配列からアクタを操作する
配列に格納したアクタを操作するには、配列の要素を指定してやれば良く、その後は通常のアクタと同じように扱えます。例えばインデックス番号が1のアクタを Z方向 に移動したいなら、以下のような処理となります。
アクタの内部関数や変数等にアクセスする場合はキャストする必要があります。
例えばインデックス番号1のボックスの表示を 1 から 8 に変える場合は以下のキャストを絡めた処理となります。
3.Actor 配列の要素を Destroy するとどうなるか
Actor 配列は Integer 配列などのような数値を入れる配列とは違い、少し特殊な挙動をします。下の処理のように、インデックス番号1のアクタをインデックス番号0に上書きし、インデックス番号0のアクタを Destroy します。
すると下画像のように、始めインデックス番号1に入っていたアクタが Destroy されます。
その後に、インデックス番号1のアクタを Destroy する処理を追加してみると、実行後にエラーが告知されてしまいます。
また、先に1を消し、次に0を消しても同じエラーが出ます。
ということは、配列への代入はアクタ本体というよりはポインタに近い考え方だということでしょう。
インデックス番号0にも1にも、1と書かれたボックスへのポインタが入っているならば、二重の Destroy でエラーが出るのは当たり前です。
また、当然上書き後は0と書かれたボックスへのアクセスが出来なくなる点にも注意が必要です。
4.Actor 配列のシフト処理
Destroy の挙動を踏まえて、Actor 配列のシフト(隣のインデックスへ要素を入れ替えていく)処理を考えてみましょう。下画像の5つのアクタを左シフトする場合、インデックス番号0に1の要素を上書きしてしまうと0を操作できなくなってしまうので、先に Destroy しておく必要があります。
さらに、インデックス番号3に4の要素を上書きすると、インデックス番号3と4が同一の要素を差すことになり不具合の元となるため、インデックス番号4に新しいアクタを上書きする必要があります。
上の画像の例で、インデックス番号4に新しいボックスをスポーンさせ上書きしても良いですが、シフトした末尾を空にしておきたい場合もあります。
その際は、適当なアクタ変数を Variables の「+」から追加しておき、当該インデックス番号に上書きしてやれば良いです。
5.座標を二次元配列で管理する方法
二次元配列でのアクタ管理方法を考えるため、下動画のような挙動をする処理を見ていきましょう。盛大に音ズレしていますがご容赦願います。
これは (0,0) から (4,4) 座標までランダムにボックスか空間が配置されており、
- 60フレーム経過するとランダム座標のブロックを一つ消し(指定座標にブロックが無ければ処理を行わない)
- 120フレーム経過するとz軸の下方向にブロックをシフト、z軸の最上階にはランダムでボックスか空間を配置
前項のシフト処理と同様、こちらもやっていることは配列にブロックか空間のアクタ(Pawn)を上書きしているに過ぎません。
※ブループリントには二次元配列は用意されていないが、配列を疑似的に二次元配列として考えることができます。詳細は Unreal Engine 4 で作るテトリス Part.02 の「3.疑似二次元配列化のためのマクロを作成」で解説しているのでご覧ください。
メインの処理は以下となります。
Event BeginPlay で目盛り用の黄色いブロックと、ランダムで灰色のブロックを配置。
Event Tick でランダム座標のブロックを消す処理か、シフト処理を行っています。
シフト処理の関数内では、以下のようにブロックを SetActorLocation で移動する毎に、配列のインデックス番号も移動するようにしています。これで座標管理ができるわけです。
また、空間の場合に空のアクタ Kara を上書きすることにより、座標と配置の整合性が取れるようになっています。
ブロックを消す処理では、指定座標が空アクタ Kara かどうか判定してから Destroy 処理を行うことで、不具合を回避しています。
これを応用すれば、アクタの二次元配置を自由に操作できることが分かるでしょう。
尚、この処理に使った他の関数、マクロは以下となります。
0 件のコメント:
コメントを投稿