Gaming Life

一日24時間、ゲームは10時間

UE4 ビヘイビアツリーで巡回+攻撃する敵AIを作るのに苦労した話

 UE4にはビヘイビアツリーと呼ばれるAIを簡単に作れる機能がある。 人工知能の作り方 によるとXBoxで2004年に発売された『Halo2』の開発のため発案、GDCで発表されて以降ゲームAIの分野に置いて最もポピュラーな方法として確立されたらしい。

 ビヘイビアツリーではキャラクターの行動をBehavior(日本語で振る舞いという意味)を基本として捉えツリー構造で表現する。原理としては、ルート(根)から実行順序を決める中間ノードを介して、枝の末端に実際の振る舞いを記述。中間ノードに従い末端の振る舞いを順に実行するだけの実にシンプルなもの。UE4ではこのツリー構造を視覚的に作ることができるので非常に楽にAIを実装することができる……というのが初心者なりの理解。  ビヘイビアツリーの更に詳しい原理や成り立ちは前述の本を読めばだいたい理解できるし、UE4での実装の仕方は皆大好き極め本や 公式のクイックスタートガイド(日本語化されている)を見れば大丈夫。

 だと思ってた。

 極め本や公式クイックスタートガイドを見ながら、上記程度の単純なAIを実装できたがツイートの日付を見ればわかる通りたったこれだけでかなりの時間を要してしまった。復習のため、また、今後勉強を始める方の為に躓いた点と解決策を書いておく。

実装したい機能

  • 使用テンプレート: TwinStickShooter
  • バージョン: UE4 ver4.18.1
  • 普段は指定の巡回ポイントを順に回る。巡回ポイントについたらその場で数秒停止。周りを監視する
  • プレイヤーを発見したら1秒程度停止する(攻撃準備の表現)。その後その場にとどまり0.2秒刻みでProjectileを発射して攻撃する
  • プレイヤーが視界から消えたら攻撃を止め5秒その場で停止、見つからなければ巡回行動に戻る

 完成版ビヘイビアツリー(画像)

f:id:ai_gaminglife:20171213212358p:plain

1.宙に浮いているキャラクターの移動

 極め本や公式のチュートリアルでは地面に足を付けたCharacterを動かしているのでそのままナビメッシュを利用すれば移動できる。だが今回使用するTwinStickShooterテンプレートは宙に浮いているPawnのためそのままではナビメッシュを利用できない。「Move to Location」や「Move to Actor」の「Use PathFinding」のチェックを外せばナビメッシュなしに移動できるのだが直線的にしか移動できないので後で不具合が起きそう。そもそもこの問題に直面していた時チェックを外しても移動すらできなかった。

 これは画像のようにCharacterクラスを無理やり使って解決した。

f:id:ai_gaminglife:20171213212423p:plain

 見た目上宙を浮いていればいいじゃないかと考えCharacterクラスのSkeltal Meshを空(カラ)に、新たにStatic Meshコンポーネントを追加してコリジョンを画像のように置いて解決した。ちなみに「Use PathFinding」のチェックを外しても動かなかったのはCharacter Movement Componentを追加するのを忘れてただけだった(なんじゃそれ)。

2.プレイヤーを最初に発見した時のみ起こす行動の分岐方法

   プレイヤーを最初に見つけた時のみ構えの動作をとってから(まだ構えのモーションは未実装)攻撃に移行させようとしたのだがこの分岐をどうやればいいのか最初は全くわからなかった。

 今回はブラックボードに新たにBool型Key「FirstSearch」を追加して解決。

 AIControllerで「Set Value as Bool」を使ってTrueに初期化しておき、   f:id:ai_gaminglife:20171213212501p:plain

 自作のデコレータ「TrueCheck」「FalseCheck」でKeyの情報を取ってきて分岐させた。

f:id:ai_gaminglife:20171213212523p:plain f:id:ai_gaminglife:20171213212529p:plain

(PerfomConditionCheckAI関数をオーバーライドしている)

 後は適切なときに「FirstSearch」をTrue/Falseに切り替えれば良いだけ。

 3.IsAtLocationについて

 チュートリアルのこの頁 では「IsAtLocation」というデコレータを使っているのだが これがどういう意味なのかわからない。未だによくわからないので今回は使わなかった。(どなたか教えてくださると助かります)

(追記)alweiさんにTwitterで教えて頂きました

 だそうです。確かにこれは便利だ…時間があればこれを使ったものも作りたい。

 

4.Projectileをプレイヤーが視界にいる間連射する

 これはビヘイビアツリーのAttackタスク内で以下の画像の通りにして実現した。

f:id:ai_gaminglife:20171213212552p:plain

 プレイヤーの位置を格納している「TargetLocation」から自身のLocationを引いて正規化(normlize)した値と「FindLookatRotation」で自身からプレイヤーへの向きを得て「FireShot」関数を呼び出す。  FireShotの中身はこんな感じ。ほぼテンプレそのまま。 f:id:ai_gaminglife:20171213212558p:plain f:id:ai_gaminglife:20171213212616p:plain

 このAttackタスクを実行後にWaitタスクが実行されるように置いて、連射できるようにした。

まとめ

  「IsAtLocation」デコレータや タスク内でTimerやDelayを実行するとどういう扱いになるかなどまだ良くわからないところもあるがとりあえずここまでで最低限やりたかった機能が実装できた。独自の方法のためもっと効率のいい方法はあると思うががむしゃらにやってみると案外うまくいくのでとりあえず効率無視でやってみる、と言うのが大切だと改めて感じた。

 12月中にはこのゲームを遊べるようにしたい。

ゲーム向けな美味しい乱数を生成する

 色々思うところがあって乱数について学んだことをスライドにまとめてみた。

 本来大学のLT大会で発表予定だったのですが長過ぎるのでブログで公開する。(次回のLT大会でこれのショートor発展verをやる予定)

 ネタが多めだが数式は殆ど使ってないので読みやすいはず。感想、間違ってるとこなどあればコメントTwitterで教えてください。

UE4 ちょっと見栄えのいいワープ機能を実装してみる

先日の第三回UE4GameJamに参加して以降、他の人の組んだBPを読み込んだり、いろんな機能を実験していたのだがその中で色々応用の効きそうなBPが実装できたので自分用のメモがてらブログにまとめる。

環境

使用ver: UE4 1.8.2

使用テンプレート: TwinStickShooter

ワープポイントのエフェクト

 今回は無料で手に入る「InfinityBladeEffect」内の「P_Summon_Portal」を利用。InfinityBladeEffectは実用的な上中身を見てるだけでCascadeの勉強になるので神。

ワープ機能を実装する

 これは ヒストリアさんのブログ が詳しいので参考にされたし。ただしこの記事では一つのActorを継承したBP「BP_WarpPoint」に「Box Collision」を二つ持たせて解決してるがこれでは使い勝手が悪いので、いわゆる「ダイレクトブループリント通信」を利用した。

 「BP_WarpPoint」型の変数を用意してDetailsから「Instance Editable」にチェックを入れる。これにより設置したレベル上でその変数の中身を変えることができる。 (ダイレクトBP通信については公式 がとても詳しいのでそちらを見るべき )

 レベル上にこの「BP_WarpPoint」を二つ設置し(それぞれ①、②とする)Details->Defaultから先程用意した「BP_WarpPoint」型の変数に①には②、②には①をセットする。これでヒストリアさんのブログで紹介されていたワープ機能と同等の機能が得られるはず。

ワープ中入力を受け取らないようにする&黒画面フェードアニメを実行する

 ワープ中に移動できるようにすると変なので

ワープポイントに入る ->移動を禁止 ->黒画面フェードアウト ->ワープ ->黒画面フェードイン ->移動禁止を解除する

という一連の機能を実装してみた。以下、順を追って説明する。

①移動を禁止する  いろいろな方法があるが今回は「SetActorTickEnabled」を利用した。このノードは「Enabled」がFalseの時入ってくる「Target」のEvent Tickが実行できないようにする。今回はこれで問題なく動くが、ワープ中もTickを実行したい場合はフラグを立てて分岐させれば良さそう。

②黒画面フェードアウト、フェードイン  これは alwaiさんのブログ が非常に詳しいです。ほぼこのサイトのままなのでフェードアウト、フェードインアニメーションの作成の仕方は省略。

 ブログの手順に従って作成したUMGアニメーション、「Fadeout」、「Fadein」を以下の関数で呼び出します。

f:id:ai_gaminglife:20171129022103p:plain f:id:ai_gaminglife:20171129022120p:plain

 最終的には以下のようになりました。

f:id:ai_gaminglife:20171129022131p:plain f:id:ai_gaminglife:20171129022135p:plain

 実際動かした動画。

まとめ

  • InfinityBladeEffectは神。
  • ほぼ独学でここまでやってきたけど3ヶ月も使ってると流石に慣れてきた。
  • 劇場版アニメゴジラ早く見たい

 最近はメトロイドライクなゲームの開発がストップしているので次回もTwinStickShooterテンプレートを改造するか、乱数について色々実験するかも。

UE4進捗1-4 MaterialInstanceDynamicを使ってマテリアルの色を変える

 pythonの勉強を始めたせいでUE4を触る時間が少なくなっているがブログを更新していかないと企画すらボツになってしまいそうなので大して変わってないが記事を上げる。    Blenderで自作のモデルを作成、マテリアルの編集は主にUE4でやっている。中身は殆ど aiweiさんのブログ のままなので実装はそちらを参考にしてください。変更点はこのモデルは贅沢にもマテリアル二つで構成されているため「Get Material」「Create Dynamic Material Instance」のElement Indexを1に変更したことくらい(これで一時間ほど悩んだ)。

UE4進捗1-3 爆弾を打ち出す方向を決める(1)

現在作業中。Twitterで経過報告はしてますが中身はまだ見せられるようなものではないので、もう少しブラッシュアップしたらブログ更新します。   最初独力でできる気がせず、 UE4ANSWERHUBで質問させて頂きました。するとすぐに詳細な回答が帰ってきました。回答してくださったPAVI_PAVIさん、unaunagiさんに対してこの場を借りてお礼申し上げます。

UE4進捗1-2 SideScrollerテンプレートでエイム方向を制御する

 こんにちは。未だにブログでの口調が決められません。暫く統一感のない文章になると思いますがじき直して行くので許してください。

 前回記事で、UnrealEngine4付属のSideScrollerテンプレートを少し改造して弾を撃てるようにしましたが、プレイヤーが向いている方向にしか撃てない、テンプレートのままのBPだと同じX軸上にしか敵はいないのに、左から右にキャラの向きを変える時一時的に正面を向いてしまい、その向きで弾を撃つと手前方向に飛んでしまうという不具合が有りました。今回はそれを直していこうと思います。

プレイヤーが正面を向いてしまう問題を解決する

f:id:ai_gaminglife:20171019004042p:plain

 これはすぐ解決しました。「Input MoveRight」の出力ピンであるAxis Valueに-90をかけた値を「Make Rotator」ピンのZにつなげてRotatorを得ます。それを「set ActorRotation」に繋げば終わり。上の画像では間に色々処理をしていますがエイム制御に用いているので次で説明。

弾を8方向に発射できるようにする

 まずコンテンツブラウザからblueprint -> enumrationを選んで新たに作成しましょう。わかりやすいように AimDirection と名前を付けました。  enumとは列挙型のことで、わからない方は各々調べてください。なんせ私もこれを作っている途中で知ったので……  AimDirectionの中身はこのようになっています。

f:id:ai_gaminglife:20171019004058p:plain

 以降は込み入ってるのでざっくり方針を説明して実際のBPの画像を示すことにしましょう。

  1. Project Setting -> Input から MoveUp を新たに定義。中身はW(Scale:1.0)、S(Scale:-1.0)。

  2. 「InputAxis MoveRight」の出力ピンからBranchで場合分け。それに応じて SideScrollerCharacter 内で新たに定義したAim Direction型の変数 Horizontal Aimをセットする。

  3. 「InputAxis MoveUp」の出力ピンからBranchで場合分け。それに応じてAimDirection型の変数 Vertical Aimをセットする。

  4. 「Event Tick」から「Switch on AimDirection」を使って9パターンに実行ピンを分ける。AimDirection型の変数 FinalAim Directionに対応する文字をセット。

  5. 確認のためFinal Aim Directionの中身を表示する関数「Debug Aim Direction」を実行。

  6. 再び「Switch on AimDirection」を実行し、それぞれ対応するVector型変数 Aim Vectorをセットする。 例:「Up」の時は(0.0, 0.0, 1)、「Right Down」の時は(0.0, 1.0, -0.3)

  7. 弾のBP、BP_ShotFireに新たに Vector型変数、 SpawnVectorを定義。これは「編集可能」と「スポーン時に公開」にチェックを入れる必要がある。

  8. 7の作業をするとスポーン時にActorに引数を渡せるようになる。Spawn Actorに、Aim Vectorをコピー。

  9. 「Construction Script」に「Set Veloctity in Local Space」を繋げる。これでProjectileMovementコンポーネントの方向を動的にセットできる。引数にはSpawn Vectorを使用。

f:id:ai_gaminglife:20171019004111p:plain f:id:ai_gaminglife:20171019004123p:plain f:id:ai_gaminglife:20171019004138p:plain f:id:ai_gaminglife:20171019004151p:plain

これで出来たはずです。

振り返り

  • enumは超便利。
  • バクダンはこの方法だと投げ飛ばす感じにならないので今後の修正点。
  • 動きながらしか弾が打てない。

劇場版Fate/HF第一章感想覚書。

 劇場版Fate/Stay Night Heven's Feel 1.presage flowerを初日に鑑賞しました。もうそこらじゅうで言われている通り、期待以上の仕上がり。感動をなんとか言語化したいんですが、この作品に能う感想・考察を書ける自信がないので箇条書きでごまかします。

 以下、映画、原作のネタバレ有り。

序盤30分のサプライズにHFの全てがあった

  • 一切予告になかったほぼオリジナルの約30分の日常パート。これでもうやられた。HFは前2ルートで藤ねえと並んで日常の象徴だった桜が実は聖杯戦争に生まれながらにして関わっている存在だったことが明らかになる「日常の崩壊」が一つのキーワードですが(実際監督も舞台挨拶、パンフで言っていた)その崩壊する日常を贅沢に30分使って書いてくれるとは思わなかった。それも完璧に。

  • 目にハイライトが入っていない桜(中学生)。そしてハイライトが入り我々がよく知ってる桜になってからの健気さ、あざとさ、時折リボンを触って姉のことを思う儚さ。あまりにもかわいい。流石きのこ公認桜研究家監督。

  • 藤ねえが眺めていたアルバム。これまでHollowくらいでしか慎二と士郎の仲の良さは描かれて来なかったけどアルバムと言う形で明らかにしたのはいい表現だった。「あの」慎二君にも純真な時代が合ったのだなあ。

  • 桜「兄さんは嫌いな人が好きなんです」

  • 士郎と小競り合いになる慎二。素直じゃなさ過ぎる。

  • そこまでにしないでもっと出てほしかった藤ねえ。特典ドラマCDではガッツリ出てくるので皆聞こう。

  • 津嘉山さんの演技が凄すぎる。コナンのトマス・シンドラーといいオトナ帝国(しんちゃん)のケンといい津嘉山さんのやる役は皆好き。機会があればFGOでも爺キャラ演じてほしい。

日常の崩壊。聖杯戦争の始まり。

  • 予想はしていたがセイバーとの出会い含め共通ルート部分はOPの裏でダイジェスト。

  • セイバー「UBWの時といいufotableは私と士郎の出会いの描き方が雑じゃないですか?」

  • メインヒロインじゃないし仕方ないね。

  • 外道神父登場。相変わらずの黒幕感。

  • ぐるぐる楽しそうに踊るイリヤ。しかしこれは桜ルートなのだ。

  • バーサーカーUBWの頃と比べても更に進化。鉄の塊感が更に増した。多分第三部だけど泥に飲まれたverのあのバーサーカーとの戦いも期待。

  • 理想をだいて溺死しかける士郎君。

  • 慎二君即オチニコマ。これは悔しい。

  • 美綴の扱いがそこそこ丁寧なライダー。この辺はHollowに続く。

  • 臓硯再登場。虫の表現が進化し過ぎである。

  • 佐々木小次郎、消滅。UBWキャス子に肋骨ぶち開けられた時と違って中身がなく不気味だった。

  • キャス子ハサン先生にブチギレ。

  • 長年謎だったキャスターがやられる時ルールブレイカーを持っていた理由が明らかに。そういえばハサンは佐々木小次郎の中から出てきたんだからまだキャスターとの契約が残っていたんだなあ。自暴自棄になっていたかザバーニーヤの呪いから抜け出そうとしてやったのだとばかり。

超迫力の戦闘。キャラの表情にも感動。

  • 凛が桜を心配する時の顔があまりにもあまり。アニメUBWでも美綴に「笑わないでしょ」と追求されたり#16で凛に異常性を指摘されたときに見せた士郎の表情がアレだけでアニメ化された価値があると言わしめただけあってufoの表情描写には心配していなかったが映画でも問題はなさそう。黒桜と凛のあのCGも期待してます。

  • ランサーvsハサン。多分第一部一番の山場。

  • まさかの高速道路からの戦闘スタート。パンフでこの辺のメイキングは載っていたけどCG技術が凄まじ過ぎる。

  • ランサー無双。あっちから某女性声優の叫び声が聞こえた気がした。

  • ランサーの無駄に姿勢のいい走り。カリオストロ感があった。

  • 矢避けの加護発動。なんで3回以上避けられるんですか!FGOにもその機能ください!

  • 原作通り龍洞寺の池に舞台を移しての戦い。初映像化のザバーニーヤ。ここは原作者の監修で修正が入ったらしい。それに見事応えて見せるufotable

  • 触手に絡め取られる無表情のランサー。女性声優も倒れて運ばれていった。

  • キャスター(死体)。原作と違いここでルールブレイカーを見る士郎。キャスター捨て身の攻撃が流星ロックマンアポロンフレイムのあの技にしか見えなかった。

  • 黒い影初お目見え。士郎が影から呪いの一部を受けた時の画面が恐ろしいのなんの。

  • 桜に叱責されるセイバー。士郎が自分から傷つきにいったのに……

  • ドルビーサウンドで聞ける中田譲治の喘ぎ声(誤解)

  • 泰山店主のビジュアル初公開。なんとなくGUILTY GEARの紗夢ぽかったのでドラマCDに出る時は松嵜麗さんで声を当ててほしい。

  • セイバーvs真アサシン。風除けの加護で風王結界を躱し黒い触手の攻撃をヒットさせる見事な立ち回り。それにしてもここ最近元祖セイバーさんの活躍の舞台がロクにない。

  • 助けにやって来るライダーさん。1vs1だとハサンは弱いのだ。

  • 士郎、黒い影と再びのご対面。この時の無音と雪が不気味さを増長させる。

  • 聖杯を求めるもオルタに止められる元祖セイバー。僕はこれを単純にオルタとバトンタッチだと読んだのですがある方は、あの聖杯は取ったところで願いは叶わないと伝えたかったと取っていました。他に解釈があれば教えてほしい。

  • 真面目に魔術の勉強をする慎二。これでも絶対に報われないのだから救いがなさすぎる。

  • ひとボケかますリーゼリット。変わらない。

  • サンダルに寒そうな白いドレスで帰りを待つ桜あざとい。あざとすぎる。だがそこが可愛い。

 以上。第二章は来年6月までに見られたら良いなぁ。期待して待ちます。