Advanced Turn Based Tile Toolkit for UE4の使い方[実践編⑤の2] ZOC:Zone Of Controlの実装 改良編

Post 2021年9月23日木曜日

Advanced Turn Based Tile Toolkit TBS(ターン制ストラテジー) UE4 アセット

ぜひ基礎編を開きながらご覧ください。

この記事は、前回の改良版の記事です。ちょっとだけ改善します。

今回から、ATBTT(このアセットの略称)のバージョンを新しくしました。


お約束
この記事作成にあたって使用した(主な)UE4バージョン4.26.2
このtoolkitのバージョンv3.2 (Live 03.09.21)

本日のゴール

前回と同じですね。ZOCの実装です。

ZOCってなに?

いわゆるZOC:Zone Of Controlってやつですね。これも前回と同じ。

概要

基本的に前回からやることは変わりません。あくまでこの記事は改良です。
なんでこの記事を出すことになったかって?
それはこのアセットの作者がアドバイスしてくれたからです。神ですかね。

実践

作者は一つ指摘をしていました。ZOCを実現するために、何も全ての敵を洗い出す必要がないだろうと。それもそうだ。なので、敵の居場所を特定するノードを改良します。
また、GridManagerの方に大きな改変を入れているのも美しくない気がしますね。
GridManagerへの改変は一部のみにして、ほとんどの改変はBP_Path側でできるようにしておこうと思います。

敵に接触するとそれ以上動けないようにする。前回と同じですね。


BP_Pathの「Run Pathfinding」関数を開きます。

この上の図の、SetとClearノードの間に、敵の位置を探る関数を作ります。


「Test」という関数を作りました。スタートのノードに入力を増やします。整数の入力です。これにStart Indexを繋ぎます。

もう一個入力を増やします。こちらも整数です。これにMove Rangeを繋ぎます。


「Grid Manager Ref」からFind Units In Range関数を取り出します。


で下記のように繋ぎます。



(※)ちなみに、「Big」Unitを使うことがある場合は、ここで場合分けをして「Find Units ~~~ Big」を使う必要があると思うので注意。

出力を一旦Arrayに変換

これで敵・味方キャラの全ての場所(Index)が判明したので、敵なのか味方なのか調べます。詳細は前回に書いてあるので、そちらを参照ください。


ArrayをLocal 変数"Unit Place"に保存しておき、For Each Loopをつなぐ。


For Each Loopの中身はこんな感じ。(実際には、操作キャラのFactionはLocal変数にしといたほうがいいような気がする)


For Each LoopのCompletedから引っ張ってきて、下記のように新たなFor Each Loopを作ってください。よくわからん人は、前回を参照してね。

このKeysが敵キャラの周囲のマスのIndexを表している。

あとは、このIndexたちを保存してやればいいのだが、そのための変数を作る。

「Reachable...Indexes」とかいう変数をコピー(Duplicate)する。※ローカル変数ではなく、通常の変数。

名前はInMoveRangeUnitsとでもしておいた。

これをドラッグアンドドロップして、Getして、「Add Items」を引っ張ってくる。

Returnノードを、Completedにつないで、最終形がこれ

詳細の説明は省きます。前回をご参照ください。


これで何はともあれ、敵の周囲1マスのマスは全て数えられた。あとは同様にルート検索に反映するだけ。

まずは最初似説明したとおり、BP_Pathの「Run Pathfinding」関数の中に、今回作ったTest関数を挟み込みます。それぞれStart IndexとMove Rangeをつなぐのを忘れずに。



次にBP_Pathの「Add Tile If Valid」関数を開きます


こんな感じで、さっき作ったIn Moveなんたら変数に、Edge Indexが含まれているか調べて、ルート検索に反映するか調べます。


これで、うまくすればちゃんとZOCが反映されるはずです。

あとはZOCのオン・オフ制御ですが、前回と同様、GridManagerに「ZOC_ON」という変数を作り、外部からEditableにしておきます。

このZOC_ONによってさっきの関数をやるかやらないか決めればいいですね。

「Test」関数の最初をこんな感じに変えます。Clearノードはあっても無くてもいいです。一応初期化で入れています。

このブランチの、FalseはそのままReturnノードにつなぎます。


「Add Tile If Valid」関数にも反映してあげましょう。以上で追記、終わり!