‫こんにちは､ ようこそ｡
‫この講義では､ ビヘイビアツリーの中の新しいもの､ サービスを紹介します｡
‫サービスとは何か､ サービスが永続的な動作にどのように役立つか､ そしてC++で独自のサービスを書くにはどうしたらよいかを調べます｡
‫早速､ 飛び込んでみましょう｡
‫これで､ AIコントローラには､ ビヘイビアツリーにないロジックがいくつか残るだけとなりました｡
‫そのひとつが､ 開始位置の設定です｡
‫これはやはり､ Iコントローラからここに設定したいですね｡
‫しかし､ 今のtickのようなことは､ ビヘイビアツリーの中から行いたいものです｡
‫私はここで何をしたいのか？
‫どうすればできるようになるのか？
‫プレイヤーの位置を設定し､ 最後に確認されたプレイヤーの位置を更新します｡
‫いずれも､ ブループリント・サービスというものがあれば可能です｡
‫では､ 設計図を見てみましょう｡
‫そこで､ 私のAIでビヘイビアツリーを開き､ メインウィンドウにドッキングさせたら､ サービスとは何かということを示す必要があります｡
‫今まで使ったことがなかったのですが､ 基本的には特定のパスがアクティブになるたびに､ tick毎､
‫あるいはそう頻繁に何かを実行する方法です｡
‫ですから､ もし「チェイス」ビヘイビアにサービスがあれば､ 「チェイス」ビヘイビアがアクティブな間は､
‫移動､ 射撃､ ウェイト付けなど､ 常に何らかのコードが実行されることになります｡
‫しかし､ もし私たちが調査中ならそれはないでしょう｡
‫まさにこういう時にサービスを使いたいわけです｡
‫では､ サービスの例を挙げてみましょう｡
‫遊んでいて気づいたのは､ AIが射程距離に入ってきて､ こちらが移動すると､ AIはこちらを見ようと回転しないのですが､
‫ここはすでに組み込まれているサービスで解決できますね｡
‫このノードを右クリックして「サービスの追加」を選択し､ デフォルトのフォーカスサービスを探すと､ 色が変わって緑色になっているのがわかります｡
‫また､ デフォルトのサービスを選択すると､ デコレータが行うようにシーケンスノードの上にではなく､
‫その下に配置されます｡
‫そこで､ デフォルトのフォーカスを選択した状態で､ 次にフォーカスするものを選択します｡
‫そしてこの場合､ プレーヤーの位置に焦点を当てたいので､ 先に進み､ 保存を押して､ 再生を押してください｡
‫そして今､ 私たちが見に行き､ 動き回ると､ 彼が回転しながら私たちを追っているのがわかります｡
‫かっこいいもの
‫今度は､ C++で同様のサービスを実装して､ プレイヤーの位置をずっと更新し､ 追跡中に最終的に判明したプレイヤーの位置を更新できるようにしたいと思います｡
‫ビヘイビアツリーの適切な場所にいるときだけ､ 最後に確認したプレーヤーの位置を実行できるので､
‫tickで実行するよりも少し効率的です｡
‫サンドボックスに移動して､ コンテンツブラウザで新しいC++クラスを追加し､ すべてのクラスを表示するようにして､ ここでどんなオプションがあるのか見てみましょう｡
‫BTサービスを探しているのですが､ BTタスクの時と同じように､ いくつかのオプションがあり､
‫Blackboard Baseもあります｡
‫例えば､ プレイヤーの位置であるべきでしょうか？
‫最後に判明したプレイヤーの位置であるべきでしょうか？
‫Blackboard Baseを選択した状態でnextを押して､ このBT serviceを呼び出し､
‫プレイヤーロケーションにアンダースコアをつけて､ 先に進み､ クラスを作成します｡
‫コンパイルが完了したら､ Visual Studio のコードに移動して､ Service Blackboard
‫Base Call を継承した BT サービスプレーヤーの場所を確認できます｡
‫それが私たちの望みでした｡
‫さて､ これからどのような機能でこの中に入っていくのでしょうか｡
‫さて､ できるだけシンプルな機能で動かそうと思います｡ 基本的には最後に判明したプレイヤーの位置の値を設定するだけです｡
‫このキーはビヘイビアツリーで設定されますが､ ここではテキストではなく､ プレイヤー
‫-- ロケーションを取得して黒板キーに設定します｡
‫また､ 視線チェックは行いません｡ ビヘイビアツリーの中で､ 追いかけるときだけ実行するのであれば､
‫視線チェックは必要ないからです｡
‫私たちは､ 自動的にそれがわかっているプレーヤーを見ることができます｡
‫そこで､ もうひとつ､ サービスの中で行うことを簡略化しました｡
‫BTサービスのメソッドコールを取得する方法を知っていれば､ これはかなり簡単なはずです｡
‫そこで､ BTのサービスにはどんなものがあるのか､ 見てきましょう｡
‫ドキュメントはどうなっているんだ､ 何ができるんだ？
‫主なメソッドは､ "Become relevant" "C relevant" "the tick node" "search start "です｡
‫検索開始時｡
‫特に興味はないが､ ティックノード｡
‫そう､ そこで､ このサービスがアクティブな経路にあることを常にアップデートしてもらうのです｡
‫だから､ そういうときにこそ､ 実装したいんです｡
‫私たちは､ このファイルを検索して､ ここにある完全な署名を見つけに行くのです｡
‫ここにあるのがわかります｡
‫えーと､ どのセクションにあるんだっけ？
‫保護されたセクションの下にあります｡
‫そこで､ 作成したBTサービスに行き､ 保護されたセクションを作成します｡
‫そして貼り付けます｡ BT Serviceは親クラスから自分自身で継承していたので､ ここでは自動的にオーバーライドされていますが､
‫自分自身で再度オーバーライドしても問題はありません｡
‫コントロールシフトPで実装を作成し､ superに呼び出したいのです｡
‫そこで､ スーパーティックノードが欲しいのですが､ 自分のコンプとノードのメモリを渡したいのです｡
‫あと､ えーと､ 他にもいろいろあるんですけど｡
‫Delta秒と､ 同様に渡す必要があるものがあり､ 最後にセミコロンでtickノードの実装を終了させる必要があります｡
‫ここでは､ 基本的にIコントローラCPから､ 黒板コンポーネントを取得し､ vectorとして値を設定する動作を行いたいと考えています｡
‫さて､ オーナーコンポーネントリファレンスから黒板の部品を入手する方法がわかりました｡
‫ということは､ かなりわかりやすいですね｡
‫owner comp dotを実行し､ get blackboard componentを実行します｡ ここで､ ビヘイビアツリーのフォワードスラッシュ黒板コンポーネントをハッシュでインクルードする必要があることを思い出してください｡
‫そして､ 矢印演算子を使うことができます｡
‫そして､ ここでできることは､ 値をvectorとして設定すること､ そしてキーが必要であることです｡
‫まあ､ 対処の仕方はわかっているのですが､ ちょっと記憶をたどってみましょう｡
‫BTサービスのアンダースコア黒板ベースにアクセスすると､ タスクと同じように､ 黒板を選択状態にするキーがあるのがわかります｡
‫それを利用するのです｡
‫Get selected Blackboard Keyはビヘイビアツリーで選択されたキーを取得し､ 次にベクター値を取得します｡
‫それをどこで手に入れるのか？
‫AIコントローラーと全く同じにします｡
‫これからプレーヤーを......何よりもまず､ このトップで｡
‫そして､ これがNULLかどうかをチェックし､ ゲームプレイの静止画も含める必要があります｡
‫そこで､ ゲームプレイのスタティックがコントローラCPからプレイヤーサービスのプレイヤーロケーションにインクルードされていることを確認しましょう｡
‫そして､ もしプレイヤーのポーンがヌルポインタと等しい場合は､
‫再び早期にリターンすることになります｡
‫そして､ プレイヤーポーンを使用して､ アクターの位置を取得します｡ また､ ここでインクルードを行う必要があるかもしれません｡
‫どうするかは､ これからです｡
‫まあ､ 安全には越したことはないですからね､ こういうのは明示的に｡
‫そこで､ ゲームフレームワークのincludeを行い､ フォワードスラッシュを行います｡
‫Hにポーンと置かれるので､ ここで全てを確認した上で､ vectorとして値を設定しているだけです｡
‫それだけで十分なはずです｡
‫では､ コンパイルして､ これがうまくいくかどうか見てみましょう｡
‫実は､ もうひとつ｡
‫おそらく素敵なきれいな名前が欲しいので､ ここにコンストラクタを用意する必要があります｡
‫そこで､ クラス名となるコンストラクタを含むpublicセクションを作成し､
‫その実装を作成していきます｡
‫自分の実装をtickノードの実装の上に持ってきて､ ノード名をit
‫should be update player locationに等しく設定して､ ビルドして動作するか確認してみましょう｡
‫セミコロンが抜けていたようです｡
‫もう一度やってみよう｡
‫それがうまくコンパイルされると､ 敵に乗り移ることができるんです｡
‫私や､ 設定の焦点と同様に､ 我々はここに表示されているプレイヤーの場所として持っている新しいサービスを追加したいと思います｡
‫これは､ 0回ごとにカチカチと音を鳴らすことを望んでいることがわかります｡ 4から0へ｡ 6秒
‫これはtickを使うよりも良い方法です｡ なぜなら､ tickはここで毎フレーム実行されることが分かっているからです｡
‫これは実行頻度が少ないので､ 良いことだと思います｡
‫そして､ 細部に入り､ 黒板キーを作成し､ ドロップダウンして､ 更新したいのはプレーヤーの位置だけでなく､
‫最後に確認したプレーヤーの位置であることを選択することができます｡
‫もう一つのサービスノードは､ AIコントローラの動作として､ ティックに潜り込み､ 何が残っているかを確認するために作成します｡
‫ここでやるべきことは､ 視線が合っているかどうかを条件としてプレイヤーの位置を更新することです｡
‫そこで､ プレイヤーの位置を更新させるようにしたいのです｡
‫見通しが良ければ､ その場所をクリアにする｡
‫つまり､ 少し変わった動作になるので､ 新しいサービスノードになるわけです｡
‫新しい新しいC++のクラスを追加する予定です｡
‫すべてのクラスを表示し､ BTサービス､ アンダースコアの黒板ベース､
‫基本クラス､ そしてビートサービス・アンダーコアと名付けます｡
‫見かけたらプレイヤーの位置を教えてください｡
‫そして､ そのクラスを作成してください｡
‫しかも､ ほとんど見たことのないものばかりですから､ このサービスを導入するのはあなたのチャレンジになりますね｡
‫つまり､ AIコントローラーにあるコードを使ってチックノードを実装するわけです｡
‫目安としては､ BTサービス内からAIコントローラーのポインターを手に入れることです｡
‫これはBTタスクでやったことと全く同じなので､ AIコントローラーのポインターを手に入れるためのガイダンスとして使ってください｡
‫視線を確認するためには､ AIコントローラーのポインタが必要です｡
‫視線はAIコントローラーのメソッドであることを忘れないでください｡ そして､ 視線のチェックに応じてキーを更新またはクリアしてから､
‫このノードをビヘイビアツリーに配置する必要があります｡
‫このサービスを実行するために､ ビヘイビアツリーのどのレベルが適切だと思われますか？
‫それをどう考えるか｡
‫ちょっとアゴを掻いて､ ビデオを一時停止して､ やってみる｡
‫なるほど｡
‫お帰りなさい｡
‫そのため､ Visual Studioのコードの上に新しいビューティサービスを開くことができました｡
‫このヘッダーはほとんど同じになるので､ 先に進んで新しく生成したヘッダーにコピーします｡
‫例外は､ コンストラクターの名前を一致するように変更する必要があることです｡
‫次に､ コンストラクタの実装を作成し､ ノード名を付けて､ プレーヤーの位置が確認されたら更新し､
‫最後にセミコロンを追加します｡
‫今回はそれを忘れないようにしよう｡
‫次にC++に戻ってtickノードを実装し､ プレイヤーの位置がわかればコピーして渡します｡
‫CP そして､ スーパーへの呼び出し､ プレイヤーポーンの取得､ NULLリターンのチェックをコピーしていくだけです｡
‫実際､ 本体ごとコピーして､ そこから修正することになります｡
‫黒板コンポーネント､ ゲームプレイ静止画､ ポーンへのアクセスが必要なので､
‫黒板コンポーネントへのアクセスをインクルードしてコピーしています｡
‫実際､ 機能の多くはここで共有されています｡
‫このコードをどうにかして共有してもらうという考え方もありますが､ 気にするほど重複していないと思います｡
‫ここでやらなければならないのは､ アイ・コントローラーの有無も確認することです｡
‫オーナーコンポーネントまたはオーナーコンプドットゲットIオーナーがヌルポインターと等しい場合は､ この段階で先に進んでリターンすることになりますね｡
‫そして､ 次に行いたいのは､ 視認性の確認です｡
‫そこで､ if owner comp dot get I ownerを行い､ ここに矢印を書き､ ここにコントローラを入れる必要があります｡
‫だから､ ハッシュインクルードになるんです｡
‫そして､ IコントローラHになるのです｡
‫では､ lineを行いたいのですが､ ここでは正しい使い方を確認しましょう｡
‫IコントローラーのCPに移動すると､ ライン・オブ・サイト2になっているのが､ 私たちが欲しいものです｡
‫視線2......それから､ プレイヤーポーンへの視線も必要ですね｡
‫この場合､ プレイヤーポーンへの視線は確保されているのでしょうか？
‫CPでやっていることなのか？
‫再確認しておこう｡
‫はい､ そうです｡
‫次に､ 別の値を設定してきたいと思います｡
‫つまり､ プレイヤーポーンのアクター取得位置にベクター値を設定するわけです｡
‫そうですね､ 他に視界が開けていればの話ですが｡
‫ラインオブサイトがない場合は､ その値をクリアする必要があることが分かります｡
‫つまり､ オーナーコンポーネントと黒板コンポーネントを取得することに変わりはありません｡
‫それから､ 値をクリアして､ 選択された黒板のキーの値をまだクリアしています｡
‫見られたら､ コンパイルして､ うまく動くかどうか見てきましょう｡
‫コンパイルは成功した｡
‫ビヘイビアツリーに入りましょう｡
‫なぜなら､ プレイヤーの位置が設定されていることを前提に､
‫他の動作を中止できるようにする必要があるからです｡
‫だから､ いつでも設定・解除できるようにする必要がある｡
‫そこで､ トップレベルのセレクタを右クリックして､ サービスを追加し､ プレイロケーションを追加します｡
‫そして､ そのサービスノードを選択して､ 黒板キーを選択する必要があります｡ これは､ プレーヤーの位置となります｡
‫だから､ プレイヤーロケーションに設定されたその1つは､ アップデートプレイヤーロケーション､ より多くのダム1が最後に知られているプレイヤーロケーションを更新しています｡
‫そして､ AIコントローラーに移動して､ TTICにあるこのコードをすべて削除することができるはずです｡
‫そして､ 先に進んでコンパイルし､ それがうまくいくかどうかを確認することができます｡
‫エディターでプレイして､ まだ敵が近づいてくるかどうか見てみよう｡
‫走ってきて見失ったかと思うと､ また戻って来て撃ち始める｡
‫うん｡
‫基本的にはすべて以前と同じように動作していますが､ 今はすべて私たち自身がC++で書いたサービスを通じて行っています｡
‫次回の講義では､ AIが撃ち続け､ 最終的に自滅してしまうという厄介なバグを修正する予定です｡
‫現地でお会いしましょう｡