<前文>
前回、前々回と続き、データサイエンスの話ですが、先週から更に調査した結果ある結論に達しました。私がデータサイエンスに対してかなりネガティブなイメージを持っている事を分かった上で話半分で聞いてほしいのですが、データ科学者って実際は占い師と同じ事をしているじゃないの?という結論です。
勿論、新薬の研究室とかに配置されたデータ科学者は違うでしょうが、一般的な会社に就職したデータ科学者は、経営者から会社の方針に対する相談を受けてそれに対してGoかStopの判断を下す所謂軍師ポジションを担ってるように見えます。
ここではっきり言っておきたいのは、この場合、データサイエンス的に結論が出るために必要な数と質のデータは決して揃わないのにGoかstopの決断を下す所です。のでやっている事は占い師と同じです。(勿論、機械学習とか深層学習のような高尚な技術はほとんど使用しないみたいです。)
世の中には、決して科学では割り切れない部分が存在してます。社運を賭けた決断を下す社長にどうしたらいいと聞かれたら、絶対成功する方法なんていくらデータを見ても見つけられないでしょう。そんな時どうやって決断するのか。
知り合いの会社経営者が教えてくれたのですが、そういう決断を下す時に、その人はある占い師に内緒で相談するそうです。孫子の時代から、占いを参考にしてはいけない。と言われていますが、そこは経営者といえ人間ですから弱い者。聞いてしまうんでしょうね。
流石に上場企業の社長になったら占い師に聞くわけにはいかないでしょう。会議で、占い師に聞いたら失敗すると言われたので止めます。なんて言えませんからね。そこでデータ科学者の出番ですよ。
となると、データ科学者に必要なのは、機械学習や深層学習などの知識よりも、カリスマ性やプレゼン力なのかもしれませんね。
勿論、そうじゃない分野も出てくるかもしれません。例えば、陸上や水泳の部活なんかは、練習期間は2年間しかないです。である生徒は、フォームを正しくする練習に特化するのが最も成績を向上させるとか、その他の生徒はウェイトトレーニングで筋肉を強化した方がいいみたいな結論は、出来るようになるかもしれません。それだって生徒がケガをしなければ、みたいな条件付きですが。
それで、私の結論なんですが、占い師ポジションでもいいんじゃない。と思いました。
データサイエンスの応用箇所がガチガチの科学、工学分野しかなければ、独学でデータサイエンスを勉強した人がデータ科学者として就職出来るチャンスは0でしょう。学歴とか、紹介状とかで絶対にはじかれてしまうはずです。仮に入れたとしても、資料作成的なポジションで、データエンジニアとしての仕事をやらされる訳でしょう。これは修行だと割り切っても、後から来た所謂高学歴の新卒が、データ科学者としてデータエンジニアの作成した成果を取っててしまう訳です。やる価値は多分ないでしょうね。
でも占い師的な軍師ポジションで、データから拾いきれない部分を明らかにした上で、その拾いきれない部分に対してある結論を下す場合なら、経営者だって色々な人の意見を聞いてみたいはずですし。ガチガチのデータサイエンスを勉強した人が、結論は分かりません。とかになったら経営者は、お前は間違えなければこの会社が倒産しても、大学に戻って先生やれるけど、俺はこのプロジェクト失敗したら責任とって首つらなきゃならないだぞ。みたいに考えるかもしれません。そうなったらプレゼン力とカリスマでその経営者に取り入る事だって出来そうです。
カリスマが無ければ出来ないので、社員になるのは駄目でしょうね。となるとコンサルとして独立するのが良いかもしれません。書籍かYouTubeで宣伝を兼ねつつカリスマ性とプレゼン力を見せつけて悩んいる経営者の相談役に収まっていく。
結構いけそうな気がしますね。
それでは今週の勉強を始めます。
<本文>
今週は、先週行ったモンスターの追加、出現、AI、そしてアニメーションの追加をCh2に行います。余った時間はAIの勉強をします。
<モンスターの追加>
1.モンスターの追加
Skeleton Crew BundleをCh2に追加します。
しました。
2.モンスターの出現
先週のBlogで確認すると、最初にCharacterクラスからMonsterCharacterクラスを作成しています。
一応、作成する前にCh2のC++のコードに類似のクラスを作成していないか確認します。
Ch2のC++でCharacterクラスから作成したクラスは上記のRPGChracterクラスだけでした。このクラスはプレイヤーがコントロールするキャラクターのためのクラスなのでモンスターを表すC++のクラスはないようです。
次にGameModeクラスに先週書いたコードをそのまま追加します。
唯一、先週と違う部分は、元々作成したあったBeginPlay()関数内にSuper::BeginPlay()がなかったので、そこだけは省きました。
ビルドします。
成功しました。
テストします。
まず、MonsterCharacterクラスからMonsterCharacterBPを作成します。
DefaultRPGGameModeブループリントクラスを開いて、MonsterToSpawnにMonsterCharacterBPをセットします。
MonsterCharacterBPを開きMeshをセットします。
前回と同じようにサイズや向き、位置などを調整します。
Playを押してゲームを始めます。
モンスターは出現しました。
流石に、お店内にモンスターが出現しては困るので出現する場所を変更します。
マップの端っこに上記に示したような一角を作成しました。ここにモンスターを出現させます。
出来ました。
3.AIの作成
NavMeshBoundsVolumeを追加します。
MyAIControllerをAIControllerクラスから作成します。
MonsterCharacterBPを開き、AIController ClassにMyAIControllerをセットします。更に、Auto Possess AIにPlaced in World or Spawnedを選択します。
BehaviorTreeとBlackboardを作成します。
BehaviorTreeのBlackboard AssetにmyBlackboardDataを選択します。
MyBlackboardDataを開き、Keyの名前をCharacterKeyに変更します。
先週の説明では、この後でBase ClassをActorに変更すると書かれていますが、既にActorが選択されていました。
今度は、MyBehaviorTreeを開いて、Behavior Treeを作成します。
SequenceにMoveToとWaitを追加しようとしましたが、これらをCompositeから作成するのか、Taskから作成するのかが分かりません。
先週作成したプロジェクトを開いて確認します。
Taskでした。
出来ました。
MyAIControllerを開いて、RunBehaviorTreeをセットします。RunBehaviorTreeのノードのBTAssetにMyBehaviorTreeをセットします。
BehaviorTreeに戻ってMoveToにdecorator, Blackboardを追加します。Decoratorの名前をIsPlayerValid?に変更します。
次はCharacterKeyに値をセットします。
まず、NewTaskをクリックしてBTTask_BlueprintBaseNewを作成します。名前をFindPlayerServiceとします。
FindPlayerServiceを開きevent内でブループリントを組みます。
Event Receive Activationがありません。うーん。どこかで間違えたのでしょうか?
HTF do I? Basic AI From Scratch #1 in Unreal Engine 4を見たらすぐ分かりました。
FindPlayerServiceはNewTaskから作成するのではなく、
から作成する必要がありました。
作り直します。
今度は出来ました。
更に、Sequenceの所にFindPlayerServiceを追加します。これも先週のブログでは書いてませんでした。
FindPlayerServiceを開きevent graph内で、Event Receive Activationを選択します。
今度はしっかりありました。
うーん。やっぱり先週作成したブログからだけではAIの部分は作成出来ないですね。チュートリアルを見ながら確認して作成していきます。
もういきなりですが、Event Receive Activationの選択方法まで全然違ってます。FunctionのOverrideから選択してますね。
今度は、簡単に出来ました。やはりまだAIの部分は理解していないので、チュートリアルを見ながらじゃないと正しく作成するのは無理ですね。
PlayerObjectをPublicにする理由もしっかり説明されていました。
これが、PlayerObjectがprivateの場合にMyBehaviorTree内でFindPlayerServiceを選択した時にdetail内に表示される内容です。
MyBehaviorTree内からPlayerObjectの値を選択する事が出来ません。PlayerObjectをpublicにするとPlayerObjectの値は選択出来るようになります。
これでAIは完成のはずです。テストしてみます。
プレイヤーのキャラクターがNavMeshBoundsVolume内に侵入すると凄い勢いで追いかけて来ます。
出来ましたね。
ただし新たな問題も見つかりました。
モンスターがプレイヤーのキャラクターを勢いよく追いかけすぎて、NavMeshBoundsVolume外に飛び出してしまう時があります。そうなるとモンスターは全く動かなくなります。
これは問題ですが、来週以降に直す事にします。
4.アニメーションの追加
何か今週は凄い疲れてます。やっている事は先週の繰り返しなのに何でこんな疲れるんですかね。
兎に角、モンスターのアニメーションを作成します。
animation からBlend Space 1Dを選択し、Skeleton_Swordman_Skelを選択します。名前はSkelSword1Dとします。
SkelSword1Dを開いて、軸の設定をします。全く先週と同じです。
アイドル、歩く、走るのアニメーションをそれぞれの箇所にセットします。
今度は、Animation Blueprintを作成します。AnimInstance、Skeleton_Swordman_Skelをそれぞれ選択します。名前はSkelSwordAniにします。
AnimGraphを開き、State Machineを追加します。State Machineの名前はdefaultです。
Defaultの中身を作成します。
Idle/Runの中身を作成します。
Speed変数に値をセットするために、イベントグラフにコードを追加します。
これで完成です。
テストします。
MonsterCharacterBPのAnimationにSkelSwordAniをセットします。
何から何まで、全部先週と同じで方法で作成しましたが、これでアニメーションも動くはずです。
大迫力で追いかけてくれました。成功です。
<UE4におけるAIについての勉強>
どうもまだUE4のAIの作成方法を理解していません。ので今週はAIの勉強をします。
HTF do I? Basic AI From Scratch #1 in Unreal Engine 4をもう一度復習して、Unreal Engine 4 Tutorial – AIを今度こそ勉強します。
私が大学にいた時は、AIと機械学習は別のクラスでした。今、機械学習以外のAIはどこで習えるのでしょうか?AIのクラスは選択しなかったので、今となってはどんな内容を教えていたのか全く分かりません。唯一知っている事は、そのクラスを取った友達が見せてくれた教科書の最初のページにパックマンが載っていた事です。UE4のAIを見ても、まだ勉強していませんが、機械学習とは全然違うように思えます。やはりパックマンの事と言いゲーム専用のAI分野があるような気がします。
あ、そうだ!ゲームとAIで調べればいいんですね。
以下に示す本が出て来ました。
まず、三番目の本、Artificial Intelligence: A Modern Approach (3rd Edition) 3rd EditionがAI全般の定番の教科書みたいですね。
アマゾンで211人もreviewしてます。しかも高評価です。Stanford大学のAIのクラスの教科書にも使用されているみたいです。ただしゲームのAIについではないです。コメント欄をざっくばらんに読んでみると、本の内容よりも製本やキンドルの場合は図の配置などに関する文句が多いみたいです。最新の版では直っているんでしょうか?その他のコメントで面白かったのは、版が新しくなったから買い直したら内容がほとんど同じだったけど、良く考えたらAIそのものが前の版からそんなに進歩してないね。というのと、他のAIの本みたく、大袈裟に書かれてない所がいい。と言うコメントでした。
これってAIそのものは学問としては順調に進んでいるけど、世間が期待しているような革新的な発明は起きてないよ!と言う事でしょう。
ほら!やっぱり今の世間の言うほどは凄くない。まあ止めときます。この話題は。
兎に角、この本は手元に一冊は置いとかないといけない本ですね。
後、スタンフォード大学って全ての講義をYouTubeに挙げるとか宣言してませんでしたっけ。もしかしたらこの本を使用した講義もどこかで無料で見れるかもしれませんね。
探したら、ここにバークレー校のAIの講義が挙げられていました。
2012年となっているので少し古ですね。ただ最初の講義を見たらこの教科書を紹介しているので参考にはなるでしょうね。
Artificial Intelligence for GameとArtificial Intelligence and Gameは両方ともゲームのためのAIの本ですね。どっちがいいんでしょうか?両方とも2年以内に新しい版になっているので、内容的に古すぎる事はなさそうですね。両方買っといてもいいかもしれませんね。ぱらっとアマゾンで見た感じではArtificial Intelligence for Gameの方が良いように思えますね。こっちにしておきますか。
これだけ分かれば十分ですね。
それでは、UE4におけるAIの勉強を始めます。
HTF do I? Basic AI From Scratch #1 in Unreal Engine 4
新しくプロジェクトを作成してやります。後、#2もあるみたいですのでそれもやります。
一応、先週、そして今週の2回ほど、ほぼこのチュートリアル通りにAIを作成したので、このチュートリアルの勉強は今回で3回目になります。今度こそ完全に理解したいです。
今回は。4.24で作成してみます。
何これ?
Gameでいいのは分かるんですが、Filmとか、EngineeringそしてProduct Designなんてあります。中身も違うんでしょうか?
取りあえず今回はGameを選択します。
後はそのままで、一応、BlueprintかC++かの所だけC++に変更しました。
後、勿論ThirdPersonを選択しました。
1.Navigation Volumeをセットする。
Nav Mesh Bounds Volume を選択してレベル内にセットします。
こんな感じにセットしました。
そう言えば、Navigation Volumeをセットすると表示されるこの緑色の箇所はなにを表しているでしたっけ。調べて見ます。
公式のサイトによると、
Nav Mesh Bounds Volumeはレベル内に建てられたNav Meshsをコントロールするために使用されます。
Nav Meshsはレベル内のエリアのあらゆる場所でNavigation pathを計算します。
Volume内では歩けるような適切な角度で全ての表面にNav Meshは作成されます。
...
と書かれていました。
ここから以下の事が推測出来ます。
- 緑の箇所がNav Mesh。
- Nav Mesh上でNavigation pathが計算される。
- Nav Mesh上のみでAIは行動はする。
なるほど、Navigation Volumeは、ワンピースに出て来たオペオペの実のルームみたいな概念を実装しているんですね。
こんな感じ。
ただし、AIが影響を受けるのは、地面に接している緑の部分だけ。そこが違う所ですね。
(後で考えたんですけど、SphereじゃなくてCircleって言ってますね。ひょっとしてオペオペの実もNavigation Volumeと同じように地面に接している部分しか影響ないの?ジャンプしたらオペオペの実の攻撃は躱せるんですかね。)
2.AIを作成する。
Nav Meshだけでは何の役にも立ちません。使用するためには更にAIを作成する必要があります。AIを作成するためにはAIControllerとAIControllerによってコントロールされるキャラクターが必要になります。
AIControllerから作成していきます。
BlueprintからAIControllerを選択して作成しました。
所で、UE4C++ではAIControllerは作成出来ないのでしょうか?
試してみましょう。
ありますね。
一個だけUE4C++でAIを作成するチュートリアルも見つかりました。Unreal Engine 4.11.2 C++: Artificial Intelligence Essentials Part 1 - The Base。
ただこのチュートリアル、作者が途中で制作するのを中止してしまったみたいですね。
今回は基本をまず理解しないといけないので、UE4C++については後回しにします。
キャラクターはUE4C++から作成してもいいんですが、(実際、RPGのプロジェクトの方ではUE4C++から作成した。)今回はチュートリアルに忠実にと言う事でブループリントから作成します。
このチュートリアルではStatic Mesh Componentであるcubeとsphereを追加する事でH-AICharacterの形状を作成してます。
Mesh内のskeletal meshに指定する場合とどう違うんですかね。
勿論、こっちはSkeletal meshでチュートリアルはStatic Mesh Componentであるのが違いと言うのは分かっていますが。
次に、AI Controller ClassにH-AIControllerをセットします。
H-AICharacterをレベル内に配置しました。
思ったより小さいですね。まあいいでしょう。
3.Behavior Treeを作成する。
前節で、キャラクターにAIControllerをセットしたのにキャラクターが全く動かないのは何故でしょうか?理由は二つあります。
- Behavior Treeがセットされていない。
- Behavior Treeを使用するように言っていない。
では、まずBehavior Treeを作成します。
作りました。
開きます。
開くと、Blackboard Assetをセットする個所があります。
のでBlackboard Assetを作成してセットします。
ちょっと待って!!
このBehavior TreeとBlackboard Assetについて目的と役割が良く分からないので先に調べます。
公式サイトのBehavior Treesの説明です。
UE4のBehavior Treesは貴方のプロジェクト内のNPCのためのAIを作成するために使用されます。
Behavior Treeが、ブランチに保持されているロジックを実行するために使用されている間、どのブランチを実行するか決定するために、Behavior Treeのブレインとして働くBlackboardと呼ばれる別のアセットを頼ります。
これだけで結構Behavior TreeとBlackboard Assetの役割が分かりますね。
でもこれって単なるif statementではないでしょうか?
AIと言うからにはcomputerが自分で学習して行動を決定するんじゃないの?
うーん。この辺はAIの教科書らを読んだ方が理解しやすそうですね。
Blackboardを作成します。
AI-BTのBlackboard AssetにAI-BBをセットします。
次にAI-BB内にkeyを作成します。
このAIはプレイヤーのコントロールするキャラクターを見つけたら追いかけるAIなので、プレイヤーのキャラクターを保持するためのkeyが必要になります。ので
KeyのタイプにObjectを選択し、
ベースタイプにActorを選択します。
うーん。なるほど。KeyTypeはObjectしかないからBase ClassでActorを選択するんですね。でもCharacterクラスは選択出来ないでしょうか?
出来ますね。まあ、今回はActorクラスで代用出来るのであえてCharacterクラスを選ばなかったと理解します。
因みにこのKeyの名前は、
PlayerKeyとしました。
AI-BT内にBehavior Treeを作成します。
これでテストします。
動きません。何故でしょうか?
理由は二つあります。
- AI-BTのBehavior Treeはどこからも呼ばれていないので何もしない。
- PlayerKeyに値が入っていない。
ではこれらの問題を解決しましょう。
H-AIControllerを開きEvent Graphに行きます。
以下のコードを書きます。
これで、AI-BTを呼ぶ事が出来る様になりました。
Playを押してみると、NPCは全く動きませんが、AI-BTのBehavior Treeは以下に示すように確かに実行されています。
でも、良く見ると、ずっとMoveToの方を実行していてWaitは全く実行されていません。
これは、PlayerKeyの値がNoneになっているためです。
これを直します。
直しますが、その前に、このような有効でない値をもったPlayerKeyに対してMoveToを使用しないようにさせます。そうしないとコードの安全性が保てませんから。
その為には、以下に示すようにDecoratorを使用します。
これでPlayerKeyがnoneでない事を確認します。
これでPlayを押してみると、MoveToも実行されません。以下に示すように、IsPlayerValid内に赤いバーが表示されています。PlayerKeyに有効な値が入ってないからです。
オブジェクトを使用する前にそのオブジェクトが有効なアドレスを保持しているかを確認する事はC++でコード書いている人は当たり前の事で、ここで重要な事はBehavior Treeにおけるオブジェクトのチェックの仕方はこうするのかと言う事ですな。
うん。分かりました。
では、PlayerKeyに適切な値をセットします。
そのためには、まずNew Serviceをクリックして
BTService_BlueprintBaseを作成します。
名前をFindPlayerServiceに変更しました。更に、Behavior TreeのSequenceにFindPlayerServiceをセットします。
Sequence内でFindPlayerServiceを呼ぶ訳ですね。となるとFindPlayerService内でKeyPlayerに有効なオブジェクトを指定すれば良い訳ですね。
FindPlayerServiceを開いてEventGraphを表示します。
まず、Event Receive ActivationをFunction Overrideから選択します。
なるほど、流石に3回目だとよく分かりますね。前回はこの辺は何でやっているのか全く理解しないでやってました。Sequenceを実行する時にこのEventが発動する訳ですね。
これで、PlayerObjectにKeyPlayerの有効な値であるプレイヤーがコントロールするキャラクターのデータを保持するアドレスが入るはずです。
これをBehavior Treeに戻ってFindPlayerServiceを選択してPlayerObjectとKeyPlayerを繋げれば完成です。
しかし、Behavior Treeに戻ってFindPlayerServiceを選択してみるとPlayerObjectは表示されていません。何故でしょうか?
そうです。PlayerObjectがprivateだからです。
PlayerObjectをPublicにして
もう一度Behavior Treeに戻ってFindPlayerServiceを選択してみると
今度はPlayerObjectの値を選択出来るようになりました。今回は既にPlayerKeyが選択されています。
プレイを押して確認します。
完成しました。
もう疲れました。今週はこれでお終にします。
<まとめと感想>
AIの勉強は来週します。