‫こんにちは､ ようこそ｡
‫この講義では､ 行動ツリーに選択肢を持たせることについて見ていきます｡
‫例えば､ 敵が私に向かって走ってきて､ 私を見失ったら､ 私が最後に確認した場所にやってきます｡
‫では､ それがどのように実現可能なのか､ 見ていきましょう｡
‫ビヘイビアツリーの利用
‫ですから､ このパトロールの動作はとても参考になるのですが､ 実は私たちが実装したい動作ではありません｡
‫私たちが望むのは､ むしろ次のようなことです｡
‫選手の姿が見えたら､ できるだけ近づいていく｡
‫そして､ プレイヤーが見えなくなったら､ 最後に判明したプレイヤーの場所に移動して､ プレイヤーを探そうとするのです｡
‫そして､ その選択肢を使い切ったら､ また別の場所に行くかもしれないし､ とりあえずそこにとどまるかもしれない｡
‫では､ どうすれば実現できるのか｡
‫まあ､ 今のところ､ 一連の動作でこれを実現する方法はないんですけどね｡
‫私たちは､ 入手したデータに基づいて選択する必要があるのです｡
‫プレーヤーが見えるか見えないか､ プレーヤーの最終位置がわかっているかいないか､
‫そういうことを選択する必要があるのです｡
‫そこで､ これを実現するために､ 振る舞いツリーにセレクタノードと呼ばれる新しいタイプのノードが必要になります｡
‫右クリックしてコンポジットを見ると､ そのオプションのひとつにセレクターがあります｡
‫さて､ シーケンスとは対照的にセレクタはこのように実行されます｡
‫セレクタの下にたくさんのタスクがある場合､ 最初のタスクが成功するまで実行されることになります｡
‫そして基本的には､ 1人が成功するまで全員が失敗することを想定しているのです｡
‫今度は､ その逆を行ったのがシーケンスです｡
‫どれかが故障するまで､ すべて実行される｡
‫では､ なぜそれが役に立つのでしょうか｡
‫セレクタが片方を実行しても片方が成功するのはなぜか？
‫なぜなら､ 基本的には､ 実行可能な最初の選択肢を選んでほしいからです｡
‫さて､ この方法は､ 実際にセレクタの下でタスクを実行するのではなく､ セレクタの下でシーケンスを実行することである｡
‫そこで､ ルートレベルでは､ セレクタノードを行います｡
‫そして､ その下に､ このシーケンスを脇に追いやって､ 他のシーケンスを作ってみましょう｡
‫ここでシーケンスを1つ用意します｡ そして､ シーケンスの名前をsequenceからChaseのように変更して､
‫ここに別のシーケンスを追加します｡ これは､ searchのラインに沿ったものになります｡
‫そして､ 基本的にはこの2つの行動を選択できるようにしたいと思います｡
‫そして､ それらを失敗させるために､ デコレーターと呼ばれるものをノードに追加することができます｡
‫ノードを右クリックして「デコレータを追加」を選択すると､
‫さまざまなオプションが表示されます｡
‫それなら､ いろいろな方法でできるはずです｡
‫例えば､ この条件付きループを使うと､ この条件が正しい限り､ すべてのアクションをもう一度順番にループさせることができます｡
‫ここには他にも､ 視認性を重視したコーンチェックとか､ そういう素敵なものがあります｡
‫純粋なループを得ただけです｡
‫時間制限があるので､ このシークエンスの中にいるのは一定時間しかできないんです｡
‫基本的に､ このシーケンスの動作を変更するものはたくさんあります｡
‫しかし､ 気になるのは､ これが黒板状態であること｡
‫そして､ その下に書いてあるように､ デフォルトは､ このセルフアクターは設定されているか､
‫というような内容になっています｡
‫そして､ この設定がされていない場合､ 自動的にこのノードとその下のすべてのノードが失敗し､ セレクタはオプション2､
‫つまり調査に進むことになるのです｡
‫そこで今回は､ 実はこれを変えたいのです｡
‫この仕組みを変えたいのです｡
‫プレーヤーの位置は､ プレーヤーが表示されているときだけ設定されるようにします｡
‫そして､ ここでも新しい変数を追加したいと思います｡ ベクトルは､ 最後に確認したプレーヤーの位置と､ プレーヤーが表示されているときに確認したプレーヤーの位置が同じになるようにします｡
‫しかし､ プレーヤーが見えなくなると､ プレーヤーの位置は設定されなくなり､ 最後に知られていたプレーヤーの位置が､ 私たちが行きたい場所になるのです｡
‫Blackboard Baseのコンディションで､ クエリをYesに設定し､
‫プレイヤーの位置情報を設定するように変更すればOKです｡
‫プレイヤーの位置が設定されている場合､ Chaseを与えることになります｡ Chaseを与えるには､
‫基本的にmove toを行うだけで､ プレイヤーの位置に移動します｡
‫だから今､ このシークエンスのもとでは､ 他のことはあまりやっていないんです｡
‫ですから､ 実際にはこの黒板の条件もそのまま移動に乗せることができるのですが､ 撮影など他のこともやりたくなるかもしれないので､
‫とりあえずシーケンスとして残しておくことにします｡
‫そして､ この調査をしています｡
‫調査」も基本的には移動を行いますが､ プレイヤーのいる場所に移動するのではなく､
‫最後に判明したプレイヤーのいる場所に移動することになります｡
‫そして､ この条件に失敗した場合に落ちるので､ 条件を付けていないのがわかると思います｡
‫これらの黒板条件について重要なことは､ デフォルトでは､ 一度このノードの実行を開始することを決定したら､
‫それを再評価することはない､ ということです｡
‫そのため､ 何らかの理由でそのプレイヤーの位置まで移動している間にプレイヤーを見失ったとしても､ そこに到達するために努力を続けることになります｡
‫ですから､ もしこのノードの実行を中止させたい場合は､ そのためのオプションがあります｡
‫フローコントロールに行くと､ ノーティファイドオブザーバーがあり､ その下にあるんです｡
‫Observerはnoneに設定された時点でアボートする｡
‫しかし､ いくつかのオプションから選択することができます｡
‫セルフに設定することができます｡
‫つまり､ この条件が突然偽になったら､ 今やっていることをすべてやめて､ セレクタを再評価して見なさいということです｡
‫今､ 私たちは調査をする必要があるのかもしれません｡
‫注意 このオプションは優先順位が低く､ ここでハイライトされている内容が変更されていることがわかります｡
‫この黒板の条件が突然真になったら､ それまでやっていたことを全部やめて､ この追っかけ条件を実行し始めなさいということです｡
‫そして､ 最後の選択肢は両方です｡
‫そして､ これが私たちの望むものです｡
‫基本的には､ この黒板に基づいた条件が真になれば､ すぐにこのシーケンスを実行し始めるということです｡
‫falseになったら､ 即座に実行を停止するか､ それ以外の実行を停止する｡
‫私たちは基本的に､ この黒板の条件によって指示された道を常に進み､ 実行したいだけなのです｡
‫つまり､ オブザーバーがアクションを停止させ､ そうでない場合はアクションが終了するまで待ってから再評価を行うということが理解できると思います｡
‫というのも､ 現時点では､ C++に移動してもう少し余裕を持たせると､
‫Begin Playでプレイヤーの位置を設定するだけだからです｡
‫理想的には､ プレイヤーのポーンに視線が届くたびにこの処理を行うことで､ 実際に視線のコードをここでアンコメントすることができます｡
‫そして､ おそらくelseのコードもアンコメントしたいところです｡
‫しかし､ 今回はフォーカスをクリアして動きを直接止めるということはしていません｡
‫というのも､ これらを完全に削除してくることができるんです｡
‫今はそういうわけにはいきません｡
‫代わりに､ コードを削除すると､ この中でプレイヤーの位置を設定することになります｡
‫また､ そこに最後の既知の位置を設定し､ それ以外の場合はプレイヤーの位置をクリアしたいと思います｡
‫黒板コンポーネントを開くと､
‫クリアな値があり､ これはfの名前を取るだけです｡
‫そこで､ ここでは､ 私たちのティックセットを埋めるための課題を用意しました｡
‫2つの変数は､ 視線方向の場合､ 基本的にこのif文の最初の部分を埋めて､ altがあるときにプレイヤーの位置をクリアします｡
‫つまり､ 視線を失うと､ プレイヤーの位置がわからなくなるわけです｡
‫ワールドにいる敵の速度を下げて､ 逃げやすくする｡
‫そして､ 機能性を確認し､ 隅に隠れることができるか､ 最後に確認された場所に行って､ あなたを見つけようとすることを確認します｡
‫ビデオを一時停止して､ これに挑戦してください｡
‫なるほど｡
‫お帰りなさい｡
‫では､ これに挑戦してみよう｡
‫まず､ プレイ場所の設定です｡
‫それをビギンプレイから移動して､ 代わりにここに移します｡
‫そこで､ プレイヤーの位置を設定します｡ プレイヤーポーンをここで取得し､ もう一度チックする必要があります｡
‫この行をアンコメントすると､ まったく同じことを､ 最後に知ったプレーヤーの位置のコードとまったく同じ行で行っていることになります｡
‫黒板に移動して､ それをコピーして､
‫まったく同じ名前にします｡
‫つまり､ clear valueとなり､ このテキストプレーヤーの位置を､ 最後にクリアしようとする値として受け取ることになります｡
‫そして､ 先に進んでコンパイルし､ これがうまくいくかどうかを確認します｡
‫まあコンパイルは成功したんですけどね｡
‫もうひとつは､ デバッグをしやすくするために､ 敵を選択して､
‫移動コンポーネントの「歩く」を見つけて､ そのスピードを変更できるようにしました｡
‫そのため､ ここでは最大歩行速度が600となっています｡
‫400に設定して､ 簡単に逃げられるようにしよう｡
‫ちょっとゆっくり歩いて､ 先に遊びに行ってしまうのです｡
‫ゆっくりとこちらに向かって歩いてきている｡
‫逃げればいいんです｡
‫私たちは隅に隠れていますが､ ここで彼らは毎回私たちを探しに来るのです｡
‫でも､ うまくいけば､ 2つのコーナーの後ろに隠れれば､ 見つからなくなるはずです｡
‫だから､ あそこに隠れ､ ここに隠れ､ ここにも隠れ｡
‫そして､ 最後に確認された場所に調査に行くのですが､ ほら､ 角を曲がったところに頭を出しただけなのに､
‫どうしていいかわからなくて立ち往生してしまうんです｡
‫そして､ ビヘイビアツリーを見て､ これを片側に寄せて､ ゲームをもう片側に寄せて､
‫少し余裕を持たせておくとします｡
‫次にビヘイビアツリーを見てみると､ どちらもできないので､ このあたりでジャズしているのがわかります｡
‫最後に判明した場所に移動しようとして､ 成功しているのです｡
‫だから､ ここでちょっと引っかかっているんです｡
‫でも､ 私が視界に入れば､ 彼が私に向かって動いているのがわかります｡
‫私の姿が見えなくなったら､ 調査条件の方に行くんです｡
‫だから､ 視力を失う｡
‫調査するそうです｡
‫そして､ 彼が来て､ 私を見て､ また私を追いかけるんです｡
‫だから､ この動作は実際に機能しているのです｡
‫この黒板の挙動をもとに､ 追いかけようとするか､ 調べようとするかの選択をすることができるようになりました｡
‫この黒板の名前を､ プレーヤーのクエスチョンマークを見ることができるように､ ここで動作に変更しましょう｡
‫だから､ もっと読みやすくなるはずです｡
‫このセレクタがプレイヤーを確認できたら､ 追いかけましょう｡ そうでなければ､
‫調査して､ このシーケンスはもう使わないので､ 削除しましょう｡
‫これで､ ビヘイビアツリーをつなげて選択肢や順序を作り､ たくさんのタスクを組み合わせて､
‫より複雑なビヘイビアを簡単に作れることを少し理解していただけたと思います｡
‫次回の講義では､ C++で独自のカスタムタスクを作成し､ 撮影アクションができるようにする方法を紹介する予定です｡
‫次の動画でお会いしましょう｡