<前文>
面白いゲームは最初から面白い
アメリカのトランプ支持派は徹底抗戦する道を選択したみたいですね。日本の〇ウムの時の様にテロを仕掛ける位はやりそうです。しかもアメリカのトランプ支持派の数は半端じゃないので、万が一の確率かもしれませんが内戦になるかもしれません。
アニメの話とか、ネットで非常にオープンにしていた弁護士の動画を最近、久しぶりに見たのですが、この後に及んでまだトランプを支持していました。多分、彼のいる州は、銃で黒人を縛り付けておかなければ国体(州体?)が保てないのでしょう。そのためには、嘘と分かっていてもQの陰謀論に乗るしかないのかもしれません。
しかし、大多数のアメリカ人は逆に、Qのような骨董無形の嘘を信じるからコロナですら駆逐出来ないと思っています。その象徴としてマスクを装着するかしないかで逮捕者まで出ています。元々アメリカ人は、カソリックの本部の嘘に我慢できなくて本国を捨ててまで自分の信仰を貫いた人達の子孫なので、絶対に妥協しません。このQの信望者たちを全て殲滅するためには、そのために南部の州の一つや二つが無くなってもお構いなしで戦い続けるでしょう。
つまりアメリカで第二次南北戦争が起きるのは十分あり得る話なのです。更に、もしテキサス州のような強大な州が南部側について独立宣言したら、どっちが勝つのかすら分からなくなります。
日本だって無関係でいられないと思います。自民党(多数のQの信望者や関係者がいる?)が与党の立場で南部連合を正統なアメリカであると表明したら、北軍の司令官である現大統領が在日米軍を出撃させて東京の国会議事堂を爆撃する事態すら起きるかもしれません。勿論、その時には北海道に傀儡の新日本政府を作っているでしょう。
そこまでは行かなくても、内戦で弱体化したアメリカの僅かな援助を頼りに、世界で最も富める核保有国である中国と渡り合わなければならなくなります。
何か、私の話もQの陰謀論と変わらなくなってしまったのでこの辺で止めます。
ここからは、先週話した、念能力をゲームに追加する件について今週考えた事を述べます。
あれから色々検討したのですが、ゲームのコアの部分がつまらないのに、ボリュームを増やしたからと言って面白くなる事はないとの結論になりました。念能力をゲームに追加するとしても今の時点では、ボリュームを増やしただけになりそうだからです。
そこで今回はそのコアについて考察します。
ゲームの面白さには戦略と戦術があると思います。簡単に言えば戦略は準備をしっかりした方が勝つ、で戦術はその場でうまく立ち回った方が勝つです。
今回は戦術面、つまり戦闘の自由度を増やして、選択の結果が勝利に繋がる様なゲームを考えます。
戦闘中の選択ですが、念能力を追加するまでもなく現時点で、
- 通常攻撃
- 魔法攻撃
- アイテム使用
- 逃げる
の4択が出来るようになっています。
この4択のどれを選ぶかで戦闘の結果に違いが出なければなりません。
それで以下の様に考えました。
- 通常攻撃
- 武器を装備する事で上がる。基準となる攻撃。
- 魔法攻撃
- 魔法で攻撃する。属性があり、通常攻撃×2~1.8の攻撃力になる。
- アイテム使用
- HPを回復さえる薬草と、MPを回復させる魔法薬がある。
- 店で購入出来る薬草は、敵のモンスターが与える1回のダメージより低い回復しか出来ない。つまり戦闘中に使用しても意味がない。
- 戦闘中に使用しても効果がある高い回復力を持つ特別な薬草は、イベントでしか手に入らない。数に限りがある。
- 逃げる
- 30%の確率で戦闘から逃げれる。
これならば戦術面で工夫する事で戦闘力が高い敵にも対抗する出来ます。更に絶対勝てない相手には「逃げる」の選択も出来ます。戦術の幅が広がります。
これで行く事にします。
それでは今週の勉強を始めます。
<本文>
1.今週の作業
今週は、my AIを作成します。
2.理論
先週のアイデアを以下に示します。
何かが足りないと思っていたんですが分かりました。
それは縄張りです。
モンスターなんで、行動形式は単純であるべきなんです。
- 縄張りに侵入して来たら、追いかけて来て攻撃する。
まずはこれです。これをAIで作成します。
<知覚>
- 視覚で縄張りの境界を確認します。縄張りの外側に居る時には興味を示しません。境界内に侵入してくるかどうかだけ見ています。
< 思考>
- 特に何も考えていません。
<行動>
- 普段は、縄張りの境界上をパトロールしています。敵が侵入して来たら襲い掛かります。
まずはこれを実装します。そしてこれが完成してから障害物が縄張り内にある場合を考えます。
3.実装
まず、今までのAIがどの様なものだったかを復習します。
3.1 復習
AIControllerの実装です。
これだけです。
次はBehavior Treeです。
ここに、
- 視覚から得た情報
- パトロール
- 侵入者に突撃
などを追加していきます。
3.2 視覚の追加
まずAIControllerに視覚を作成します。
正しい設定の詳細は覚えていません。後で、Tutorialを見て確認します。
次にAIPerceptionStimuliSourceをThirdPersonCharacterBPに作成します。
設定を以下の様にします。
こっから先が覚えていません。先々週のブログで確認します。
結構詳しくまとめてありました。
次はAIControllerです。
視覚が使用されているのかの確認のために以下の実装をしました。
このポイントはOn Target Perception Update (AIPerception) を使用する事でした。
テストします。
効いていますね。
ついでにGamePlay Debuggerも使用してみます。
設定を変更してGamePlay Debuggerが使用出来るようにします。
Project settingを開き以下のように設定を変えます。
先週勉強した公式のOnline Learningではこの後にConsoleの箇所を…と言っていましたが、これだけで十分なはずです。
確認します。
動いています。
しかも視覚で認識されている事も確認出来ました。
Blackboardに変数を作成して視覚の結果をBehavior Treeに追加しましょう。
AIControllerを以下の様に変更します。
取りあえずの動作確認用としてBehavior Treeの実装を以下の様に変更しました。
Blackboard Based Conditionの設定はいじっていません。
あ、名前だけは変える事にします。先週勉強したOnline Learningで疑問文にした方が分かり易いとあったからです。
Task、PrintStringTaskは以下の様に実装しました。
先週までで学習したTaskの作成で必要な事は、
- Event Receive Execute AIを使用する事、
- FinishExecuteを使用する事、
- FinishExecuteはSuccessで返す事。
です。これらを守って作成しました。
テストします。
動いている事は確認出来ました。
今度は、Behavior TreeのDebug機能を使用してみます。
I see youが表示された所で、Pauseボタンを押します。
I see youを表示させたモンスターは目の前の奴なのでDebugの対象をMyAIController_C_2に指定します。
以下の様になっていました。
Back Intoボタンを押すとPrintStringTaskが呼ばれている事が分かります。
視覚が機能している事の確認が出来ました。
3.3 縄張りの作成
色々考えましたが、縄張りを最初から作成するのは難しいので、モンスターの周り、例えば半径150mに近づいたら攻撃してくる事にします。
Blackboardに新しく作成した変数です。
その変数の値をTrueに変更するためのServiceのIsHeInTerritoryは以下の様に実装しました。
Service内の変数の値とBlackboardのIsHeInTerritoryを繋げます。
Blackboardの変数、IsHeInTerritoryがTrueかどうかを判別するDecoratorを追加します。
設定は以下の通りです。
テストします。
あれ、追いかけて来ません。
視覚で認識はされています。
IsHeInTerritoryがFalseを返しています。
色々調べてたら原因が分かりました。
ServiceのEventであるEvent Receive Activation AIが発動していませんでした。
ServiceのEventを、試しにEvent Receive Search Start AIに変更したらモンスターが追いかけて来ました。
良く考えたらServiceの正しい作成方法知りませんでした。
ちょっと勉強します。
3.4 Serviceの正しい作成方法
ググったらこのサイトが詳しく解説していました。
後、UE4のAnswerHubの「BT Services not activating」の質問の解答に以下の解説が載っていました。
今まで気が付かなかったんですが、UE4のAnswerHubってLogInしないと見れなかったんですね。これからはUE4のAnswerHubのスクリーンショットを貼るときは引用元をはっきり書く事にします。
UE4のAnswer Hubの「BT Services not activating」の解答より引用
上記の説明によると、Event Receive Activationはbranchがsuccessを返した時だけ発動するとあります。となると先程の例で呼ばれないのは納得です。
と言うかこれで完全に解決してしまいました。
3.5 パトロールの追加
縄張りに侵入してこない限りは、モンスターはその辺を歩き回っています。最初は先々週勉強したTutorialでやったような
の様にパトロールする要所を設定する方法にしたかったのですが、この方法を採用すると全てのモンスターに一々、パトロールする要所を設定する必要がある事に気が付きました。それは大変過ぎるので適当な場所に歩いて移動する事にします。
まず適当な場所を見つけるServiceを作成します。
作成したServiceを追加して、Blackboardに適切な変数を作成してそれと関連づけます。
これで一応、モンスターはその辺を歩き回るはずです。
テストします。
近づくと攻撃してくるので遠くから観察しましたが、全てのモンスターはランダムに移動はしています。
ただし2つ問題がありました。
- 歩かずに走り回っている。
- どんどん別な場所に移動してしまう。
これらも直していきます。
3.6 モンスターを歩かせる
これは先々週勉強したtutorialにやり方が出ていました。
同じserviceを作成します。
Behavior Treeに追加します。
Max Walk Speedはぶらぶら歩いている時は150、侵入者を見つけた時は600にセットされるようにしました。
テストします。
遠くからしか観察できないのでスクリーンショットは非常に小さいですが、全部のモンスターがモゴモゴ歩いています。
成功したと思ったら、歩いている途中のモンスターに近づいても、モンスターは襲って来ません。
あれ。ひょっとして。
Does Monster See Player? の Observer abortsの設定をLower Priorityに変更したら
モンスターは散歩を中止して凄い勢いで追いかけて来ました。
Lower Priorityとはそういう意味だったんですね。
やっと意味が分かりました。
3.7 モンスターを元の位置に戻す。
これもTutorialでやりました。以下にその方法を示します。
My AI Controllerから上記の方法と全く同じやり方でやろうとしたら、Monster BPのAIはMy AI Controllerであるにもかかわらず、Get Controlled PawnをMonster BPにcastする事が出来ません。
仕方がないので以下の方法でMonsterがspawnする最初の位置をBlackboardにセットしました。
更にBehavior Treeを以下の様に改良しました。
これで3回ほど適当な場所をうろついたら最初にSpawnした位置に戻ってくれるはずです。
テストします。
戻っているみたいです。
Behavior Treeをdebugしたらモンスターは最初の位置に移動しています。
一応は出来ました。
4.Lower Priorityの機能の確認
前節の「3.6 モンスターを歩かせる」でLower Priorityの機能の意味が分りました。一応確認のテストを行います。
4.1 テストの条件
まずBehavior Treeを以下の様に組みました。
TaskのPrintStringとPrintString3は単にPrintStringを実行するだけです。
TaskのPrintString1とPrintString2 はPrintStringを実行する前に3秒間停止します。
Blackboardの変数ChooseNumberは1にセットされています。
この条件でテストします。
4.2 Noneの場合
Observer abortsをNoneにセットします。
ChooseNumberが0に変更された場合でも、実行中のノードPrint String 3は停止しないで最後までtaskの内容を実行しています。その後、変更した条件に沿ったtaskを実行しています。
Behavior treeのdebugも見てみます。
ChooseNumberの値が0にセットされました。
PrintString3のtaskが終了してSuccessを返しています。
その後で、Selectorが新しい条件にあったNodeを選択しています。
4.3 Lower Priorityの場合
今度はObserver abortsをLower Priorityにセットします。
テストします。
ChooseNumberが0に変更されると、Noneの場合と違い、実行中のノードPrint String 3はただちに中止します。その後、変更した条件に沿ったtaskを実行しています。
Behavior treeのdebugも見てみます。
ChooseNumberの値が0にセットされました。
PrintString3の作業は直ちに中止され、新しい条件にあるtaskが実行されています。
Abortが発動した時もfailureの信号が親ノードに返されると思っていたのですが、何も返していませんね。
4.4 Lower Priorityまとめ
と書きましたが、その時は、高い優先順位から低い優先順位に変更された場合でテストしています。
その条件ではLower Priorityは発動しません。
Lower Priorityが発動するのは低い優先順位にあるTaskを実行中に、条件が高い優先順位に変更された場合です。
Observer AbortがNoneにセットされている場合は、低い優先順位にあるTaskを終了してから、変更した条件に合う高い優先順位にあるtaskを実行します。
しかしObserver AbortがLower Priorityにセットされている場合は、低い優先順位にあるTaskをabortして、直ちに変更した条件に合う高い優先順位にあるtaskを実行します。
4.5 2021-01-24のブログのLower Priorityに関しての間違いを直すのか?
直しません。
このブログは滑った転んだの過程を記録するために書き始めたからです。間違えた事も立派な記録です。
2週間前は、Lower Priorityの機能を間違えて理解していましたが、今は正しく理解しています。
この正しい理解に至った過程こそが、大切であると私は思っています。
もし2021-01-24のブログを直してしますと、その正しい理解にたどり着いた過程を消す事になってしまいます。だから2021-01-24のブログは間違った事が書かれていてもそのまま残します。
もっと深い理由もあります。
アメリカに居た時に非常にびっくりした事の一つに、アメリカ社会では、間違いは、絶対に罰しないんです。どんなにその間違いで損害が発生しても、間違った場合は罰しないです。
しかし嘘をついた場合は、ものすごく厳しい罰則があります。
その時に学んだんですが、人間は必ず間違えます。間違えない事は不可能です。しかし間違いは、後で直す事が可能なんです。所が嘘は違います。嘘を突かれると、どこで間違えているのか分からなく成ってしまうんです。その結果、後から直すのがほとんど不可能になります。
だから人は、間違いには寛大で、嘘には厳しく在るべきなんです。
しかし日本では、ほとんどの場合、逆で、間違いには非常に厳しいのに、嘘には寛大です。
これはソフト制作を含めたモノづくりにとって最悪な習慣だと思っています。
だから直しません。
4.6 Lower Priority おまけ
因みに「Unreal Engine 4で極めるゲーム開発」のp414に犬がお母ちゃんと遊んでいる時にお父ちゃんが帰ってきたらの例え話でLower Priorityを説明しています。
Lower Priorityの機能を理解してから読めば、全くその通りの説明ですが、二週間前の私は理解出来ませんでした。
理由は簡単で、私が子供の時に飼っていた犬は、飯を用意してくれるお母ちゃんと遊ぶ方が、お父ちゃんと遊ぶより優先順位が高かったからです。仕事を終えたお父ちゃんが家に帰って来てもその犬はお母ちゃんと遊んでいたらお父ちゃんは無視していました。
だからこの部分を読んだとき、私は勝手にお母ちゃんと遊ぶ方が優先順位が高いと思っていました。
5. EQSの作成
Environment Query Systemなんて仰々しい言い方をしているから、非常に恐れていましたが、数値解析なんかで、面をグリッドで表し、それぞれの点に値を与え、更にinterpolationする時に、点の値をどれくらい考慮するかを重みで表します。要は、これと同じ事をやっているだけだと分かりました。なら恐ろしくないです。
なのでEQSもしっかり勉強する事にします。今まではEQSに関しては読んだだけでしたが今回は実際に作成してみます。
先週、公式のサイトのtutorialがかなり良かったので今回も公式のTutorialで勉強します。(と言うかGoogleで検索したら一番上に出て来たのでそのまま選びました。)このサイトです。
今回、私が注意して学習する点は以下の事になります。
- グリッドの作成方法
- そのグリッドに対してどうやって値をつけるのか?
- 重みの計算方法
- 出来た値と重みをどう使用するのか?
これらの点に注目しながら勉強していきます。
5.1 Environment Query System Quick Start
始める前からアレ何ですが、このTutorial、何時作成されたのかが分かりません。
以下の警告が表示されているんですが、4.26ではEQSは標準で装備されていますので、今もってExperimentalではないとは思います。
せめてTutorialが作成された日付が分かると、この時はExperimentalだったんだな。とか今もってExperimentalなのか?とか、学習者が推測できるので有り難いです。
このTutorialで以下のsystemに対しての基本的な理解が出来ると紹介されています。
5のEQSと6のEQS Contextsが分けられているのはEQSそのものとEQSの使い方の事でしょうか?興味深いです。
さらに7のAI Debugging Toolsでデバックについても勉強するみたいです。
5.1.1 Required Project Setup
わざわざこのTutorialのために新しいProjectを作成するのも勿体ないので、今あるAIの勉強用のProjectをそのまま使用します。Versionは4.24です。Tutorialは4.21を使用していますが、多分大丈夫でしょう。
Editor PreferenceのEQSにチェックを入れます。
どうでも良い話ですが、Editor PreferenceとProject Settings…は違ったんですね。
最初、同じものと思ってProject SettingsからEQSを探していました。
以下のBPクラスを作成しました。
Characterクラス、AIControllerクラス、Behavior Tree、Blackboardはお馴染みですが、これらとは別に、新たに2つのクラスを作成しました。Environment QueryからとEnvQueryContext_BlueprintBaseからです。
この二つのクラスについての簡単な解説がないか、ググって見たんですが見つからなかったです。
ショウガナイので、先に行きます。
5.1.2 Environment Query Context
早速、EnvQueryContext_BlueprintBaseを使用します。
このクラス何に使用するのか全然分かりません。しかし名前から想像するにEnvironment Queryクラスを使用するためのContextを作成するのかもしれません。
Provide Single Actor関数を以下の様にOverrideしました。
Provide Single Actor関数が呼ばれたらPlayerのCharacterを返す(この場合、ThirdPersonCharacterBPを返す)。
それだけの機能です。ここからはまだ何も分かりません。
5.1.3 EQS Setup
今度は、Environment Queryから派生して作成したEQS_FindPlayerにBPで実装していきます。
EQS_FindPlayerを開いて見ると結構寂しいです。
RootからPoints:Gridを選択しました。これがGridを作成するのでしょうか?
説明が、もろにグリッド作成します。と成ってました。
ただQuerierの周りって何処なんでしょうか?それは分かりませんね。
半径と言っているのを見ると、Gridは正方形ではなく円形みたいです。
SimpleGridのPropoertiesの詳細を以下に示します。
GridHalfSizeは半径を示しているみたいですね。
SpaceBetweenはグリッド内で値を持つ点同士の距離を示しているみたいです。
Projectionは何なんでしょうか?今はまだ分かりません。
それでは説明文を読んでいきます。
説明文によると、今、作成したSimpleGridや他の選択肢は総じてGeneratorと呼ばれるそうです。そう言えば、
と書かれていました。そして何をGenerateするのかと言うとItemだそうです。このItemは後でTestに使用されるそうです。
これだけだと謎が更に深まりますね。
そしたらTestの例が説明されていました。
この文章から推測すると、
- Context Yが先程、EnvQueryContext_BlueprintBaseから派生したクラスでOverirideしたProvide Single Actor関数が返す、GameCharacterの事
- Itemはグリットのそれぞれの点
- Testはそのそれぞれの点が持つ値の計算方法を指す。
と思われます。
Generate Aroundについての簡潔な説明がありました。
どこにグリッドを作成するかを決定するそうです。
敵のモンスターを中心にグリッドは作成するので、AI Characterは分かるのですが、querierは何なんでしょうか?
だそうです。
因みに、他の選択肢は何があるのか見てみたら、以下のクラス(item?)が表示されました。
EnvQueryContext_itemはItemつまり、単なるActorの周りに作成、EQC_PlayerContextはPlayerの周りに作成するのでしょうか?
今度は、SimpleGridにtestを追加します。
TraceはQuerierからItemが見えるかどうかと言う事でしょうか?Distanceは単にItemとQuerierとの距離を表していますね。
Traceの設定を以下の様に変更しました。
Test PurposeのFilter OnlyはQuerierが見えないitemは全部排除すると言う意味だと思います。前見たEQSの動画でそう説明していた気がします。
ContextにEQC_PlayerContextを選択しましたが、ここが意味が分かりません。EQC_PlayerContextは単純にPlayerの操作するキャラを指していると推測していたのですが違うようです。
Bool MatchはTutorialで解説されていました。
だそうです。
Distanceの方は以下の様に設定しました。
これって先週見たOnline LearningのEQSと同じ事やっているんでしょうか?
何か見覚えがあります。
先週のTutorialの記憶が正しければ、
Test PurposeのScore Onlyは点数をそれぞれのItemに付ける事で、Scoring Factorに-1を入れると、点数が反対になるはずです。
ここではDistance toでEnv_QueryContext_Querierを選択しています。
5.1.4 Blackboard and Behavior Tree Setup
ここはEQSと関係ないのでスキップします。
5.1.5 Behavior Tree: Patrol Setup
新しいtaskの作成中にGetRandomReachablePointInRadius関数を使用していました。
あ。
Reachableじゃない時はfalseを返すみたいです。
「3.5 パトロールの追加」で作成したservice、FindRandomPlaceでGetRandomReachablePointInRadius関数を使用しましたが、使用方法が間違っていました。
直します。
Branchを追加してGetRandomReachablePointInRadius関数がFalseを返した場合にも対応できるようにしました。
一応、テストもしてみます。
普通に動いています。
GetRandomReachablePointInRadius関数の返した値が、Reachableじゃない時はfalseを返すのでは無くて、GetRandomReachablePointInRadius関数の返した値は全てReachableですが、何らかの理由で値が返せない時に、falseが返されるみたいです。
上記の実装の場合、どちらの解釈が正しくても正常に作動するので、GetRandomReachablePointInRadius関数を使用する場合はこれからもこの方法で実装します。
5.1.6 Behavior Tree: In Combat Setup
Run EQSQuery を使用しました。
このTaskは先程、Environment Queryから作成したEQS_FindPlayerを呼び出します。
設定方法は以下の通りでした。
Blackboard KeyにBlackboardにある変数を選びます。これは他の Taskと全く同じです。
次にQuery Templateに使用したいEnvironment Queryから作成したクラスを選択します。今回は先程作成したEQS_FindPlayerをセットします。
Run ModeにSingle Best Itemを選択します。これは最も成績が良いitemを一個選ぶ設定です。
5.1.7 AI Controller Setup
ここはかなり複雑なコードを実装していますが、EQSとは関係ないのでスキップします。
5.1.8 Final Setup
EQSとは関係ないのでスキップします。
5.1.9 テストします
Run EQS Queryが実行されています。
Failureを返しています。
何処かにバグがあるって事ですね。
うーん。
次の章が、このTutorialの最後の章ですが、EQSのテスト方法が紹介されています。これを勉強してDebugに使用出来ないか試してみます。
それでもダメな場合は、先週勉強したOnline learningにEQSのdebug方法が紹介されていたはずなので、それを復習して試してみます。
5.1.10 End Result
GamePlay DebuggerでEQSを見る方法が簡単に紹介されていました。
それぞれの点の計算はされているみたいです。
EQS Testing Pawnの使用方法について説明されていました。
まずEQS_PlayerContextのProvide Actors Setを以下の様にOverrideします。
作成したEQS Testing PawnのEQSのQuery TemplateにEQS_FindPlayerをセットします。
Level上に配置します。
Traceが効いているのが分かります。更にDistanceの値がBP_Enemyに近い程高く、遠い程低くなっています。
5.1.11 EQS Testing Pawnいろいろ
折角なんで、EQS Testing Pawnで遊んでみます。
ThirdPersonCharacterBPにEQS Testing Pawnを重ねて置いて見ました。更に障害物は全てどかしました。
ThirdPersonCharacterBPに最も近い点が1.00で最も遠い点が0.00と表示されています。
今度はThirdPersonCharacterBPの前に障害物を置いて見ます。
障害物の後ろにある点ではTraceが0にセットされました。
EQS Testing Pawn を使用すればEQS_FindPlayerがどんな機能を持っているのかは確認出来ますね。
5.1.12 EQS Quick Start 勉強まとめ(仮)
バグがまだ直っていませんが、忘れないうちにまとめ(仮)を書いておきます。
- EnvQueryContext_BlueprintBaseがどうやって呼ばれてどのように使用されているのかが分からないです。
- 色々なTestの設定で、EnvQueryContext_item、EnvQueryContext_QuerierそしてEQC_PlayerContextから選択しましたが、それぞれが何を指しているのか不明。
- GamePlay DebuggerのEQSで、Divideが選択出来ない。
以上が不明な点です。
これらは後でもう一度検討します。
5.2 EQSのDebugの復習
Creating the First EQS QueryからEQS Gameplay Debuggerまでをサラッと見直しました。それだけでも新たに分かった事が結構あったので、まずそれらをまとめます。
<疑問1> GamePlay DebuggerのEQSで、Divideが選択出来ない。
Project Setting->GamePlay Debugger->Add Onsを見たらDivideの設定がNum/になっています。
試してみます。
Num/を押すとそれぞれのItemの値が表示されました。
もう一度押すとそれぞれのItemの値は消えました。
<疑問2> EnvQueryContext_BlueprintBaseがどうやって呼ばれてどのように使用されているのかが分からないです。
これは分かってしまえば笑い話ですが、EQC_PlayerContextとしてEnvironment QueryのTestから呼ばれていました。
<疑問3> EnvQueryContext_item、EnvQueryContext_Querierについて
これは実際にテストして確認してみます。
まず、Environment Queryから新しいクラスを派生します。Distanceと名付けます。
Distanceの中身は以下に示した様に、Generator にSimpleGridを選択し、TestにDistanceを選択しただけです。
Test、DistanceのDistance to をEnvQueryContext_Querierに指定します。
EQS_TestPawnから以下のクラスを作成します。名前はMyEQS_TestPawnとしました。
EQSのQuery Templateに先程作成したDistanceをセットします。
MyEQS_TestPawnをLevel上に配置します。
MyEQS_TestPawnから近いItemほど数値が低く、遠いItemほど数値が高くなっています。と言う事は、EnvQueryContext_QuerierはMyEQS_TestPawnを指しています。
つまり実際の場合は、EnvQueryContext_Querierは、そのEQS Queryを呼び出したAIをセットしているCharacterを指していると考えられます。
では、EnvQueryContext_Itemの場合はどうでしょうか?
これは全部、0になってしまいました。多分Itemを指定しないといけないのだと思います。後で検討します。
では、EnvQueryContext_BlueprintBaseから自作したEQC_PlayerContextの場合はどうでしょうか?
EQC_PlayerContextでは以下の二つの関数をOverrideしました。
どちらの関数が呼ばれるのかは不明ですが、(多分Overrideしているので両方呼ばれる。)どちらにしてもThirdPersonCharacterBPに対してのDistanceが計算されるはずです。
その通りでした。
ここで注意しないといけないのは、Gridとその中のItemはEnvironment Queryを呼び出したAIをセットしているCharacterを中心に作成されている事です。EnvQueryContext_BlueprintBaseはあくまでも計算するための起点の指定です。
*追記
Gridの発生場所は、Simple GridのGenerate Aroundで指定します。「5.1.3 EQS Setup」を読み直していたら自分でそう書いていました。
<>その他の役立ちそうな情報
Step to Debug Drawの数値はどのTestまでを実行するか指定出来ます。
Querying Modeは色々な結果を表示します。一番条件にあったitem一個だけの表示なども出来ます。
5.3 EQSのバグの直し
これだけEQSの知識があれば先程のバグも直せるでしょう。やってみます。
「5.1.10 End Result」で作成したEQS Testing PawnのStep to Debug Drawを1にセットしてみます。
以下に示した様に、EQS_FindPlayerの最初のtestであるTranceのContextはEQC_PlayerContextなのでThirdPersonCharacterBPから見て見えるGrid内のitemが選択されます。
されています。
次にStep to Debug Drawを2にセットしてDistanceを表示させました。
Distance toがEnvQueryContext_QuerierにセットされているのでEmenyに一番近い場所が選択されています。
これってPlayerの操作するキャラを追いかける目的ならば、EQC_PlayerContextにしないといけませんよね。
確認します。
EnvQueryContext_Querierにセットされていますが、その下の説明文に
となっています。なので
に直しました。
今度は、Playerの操作するキャラから見えて、更に最も近いItemが選ばれています。
これでテストしてみます。
今度はSuccessで返っています。
ただ、この設定だと、EQS_FindPlayerは最初のtestであるTranceが全部outな場合はfailureを返しても良い気もします。つまりFailureで返したとしてもバグとは言えない場合もあると思います。
のでこれ以上は追及するのは止めます。
6.まとめと感想
やっとUE4のAIの勉強が終わりました。大体の基礎は理解したと思います。EQSも大体は理解しました。また個人的な意見ですが、EQSは知覚、思考、行動の分類だと思考に入り、TaskではなくServiceで作成出来るべきだったのではないのかと思いました。
やっとですが、来週からはSaveの機能を改善します。