top of page
  • 執筆者の写真BTA(Kelorin Jo)

Behavior Designerを使えるようにする

PuppetMasterをベースにしたTPSキャラコンは、難所は越せてほぼ固まってきました。



もの掴んで投げて、キャラも転ばせて掴んで投げて

あとはカメラと会話システムあたりできたら、自分だけの汎用ゲームテンプレートができます。


一方、NPCにはAIをつけるべく

Behavior Designerをいじっているうちに、色々不具合があるのがわかってきました。




タスクの中身は、Behavior Designerエディターウィンドウからタスクアイコンを右クリックのメニューから、いつでも見れますが。


一番あからさまな不具合が、Moveパック(別売り)のタスク、RotateToward



C#でも基礎的なLookRotationを使ったタスクで、指定したオブジェクトの方を向くとSuccessとなって次に進むはずなのですが、高確率で止まります

どうみても指定したオブジェクト(の方向)を向いてるのに、そうと判定されないでビヘイビアツリーが止まる。。。



タスクの中身を見たら簡単なコードで、たぶん360度と0度をまたぐことができないとかでしょう。Unityでボーン回転制限のコンストレイントを作ろうとして頓挫したところなのでわかる。トランスフォームの回転の完璧な計算は、素人にはすっっげえ難しい…


単にトランスフォームで向くだけのアクションが失敗することはまずありえないので

タスク実行したら数秒で強制的にSuccessになるようにコードを改造しました。

RotateToward.csの中身に、こう追記します。

25行目にタイマーの変数tを追加して、

29-32行目、TaskStatus OnUpdata()の中、var rotation = Target();のあとに

タイマーカウントダウンとif文、ついでにデバッグログを追記

これでタイマーtが5秒たったら強制的にタスクはSuccess扱いで完了できます。


ナビメッシュAIにありがちなぬるっとした挙動が、シャキッとした素直な動きにできる!


またタイマーをpublic SharedFloat 型にしたら、Behaviorウィンドウから設定時間を書き換えれるようにできます。

ただSharedFloatはfloat型ではなく、数値参照だけで直接は扱わないの奨励の仕様です。

float a = SharedFloat .valueと書くことで、ローカル変数に中身を代入して扱えます。


24-28行 タイマーのパラメータtimeOutを作成、実処理用変数 _t を作成

30-35行 Onstart()を追加して、_tにTimeOutの中の数値を代入

39-42行 TaskStatus OnUpdata()の中、var rotation = Target();のあとに追加(動作確認したら40行目のデバッグログは削除します)


これでBehaviorエディタのインスペクタから、タスクのケツにTimeOutが追加されたのを確認できました。



他にも動作が怪しい・改造したい・あったらいいなタスクをあげると、


索敵のタスク



なぜか効かないこと多々で困るのですが、コードが長くて改造は厳しめ。

多分、コライダーで判定する対象がキャラを想定してて、

でも、キャラコンの構成は、コライダーとメッシュアニメーターとキャラコンが同一オブジェクトにあるとは限らなくて(特にパペマスのキャラコンはかなり変則的なヒエラルキー)、見つけられずタスクが失敗として処理されるって感じなのかな。



Patrol



はじめからSuccessがない仕様というのがやな感じで、Patrolタスクの優先順位を最も低くするなどの配慮が必要になります。

巡回し終わったらタスク終了とかできたらいいのに。

タスク開始時点のキャラの座標から一番近くのウェイポイントに向かってそこからスタートするものの、全てのウェイポイントを回らずリストの途中から最後までを巡るだけで、ウェイポイントをオブジェクトリストから取得できず全てD&Dで代入とか、実行中に変更できないのも痛い。

ウェイポイントのプリセット(オブジェクトリスト)を後から書き換えるとか、近接するウェイポイントを勝手に見つけて自動で追加とかできてほしいです


Wait



ただ待つだけのタスクです。これ自体はよいもので、

これとParallelと、ブール変数の中身を比較するBool ComparisonそしてSetBoolを組み合わせることで、タイマー的な処理ができますが、ビヘイビアツリーが無駄に長くなる感があり

タイマー機能をもったComPositeのタスクがあったらいいのになーと。

一定時間過ぎたら強制的に下ツリーの処理を終わってSuccessかFailure扱いにする、

また一定時間後にタイマーリセットしてタスク再開、とか。




Behavior Designerは、タスクは自作できるので足らないなら自分で作ってねという前提になってます

自作タスクの作り方は、公式にのってますが

すっごい目が滑るドキュメント 



タスクのコードをざっと見てみると、

public class Wait : Action つまりActionカテゴリのタスク 

たとえばWaitの場合は、Public overtide void Onなんちゃら()というのが目立ちます。



public override TaskStatus OnUpdate()がいわゆるUpdateに相当するとこで、

現在のタスクを実行中で、ここからreturn TaskStatus.Success;で返すと、タスクは成功で終了 return TaskStatus.Running;だと実行中(Updateを繰り返す)、といった作りになってます。

まあみたまんまの動作で改造や作成は、比較的簡単そうです。


public class Sequence : Composite つまりCompositeカテゴリのタスクは厄介そうです

Sequenceの場合は、Update()ぽいものが見当たりません。

public override bool CanExecute()というのがどうやら毎フレーム起動してそうな部分ですが、

実行中の子ツリーのインデックスcurrentChildIndexと、子タスクの状態TaskStatus(Success・Running・Failure・Inactiveの結果を返す)を上位のタスクに受け渡ししてるだけって感じです。

これを柔軟にいじくれたらいいなー




閲覧数:829回0件のコメント

最新記事

すべて表示

Comments


bottom of page