Unreal Quest5 をベースに別ゲームを作ってみよう

目次


アンリアルクエスト5とは

ヒストリアさんが過去に開催した学習用のUnrial Engineのイベントで剣を振るゲームの基本部分までできているのでここからいくつかのお題を出していくのでそれをこなしてゲームを完成しようというようなイベントでした。
今回はその完成例をベースに別ゲームを作ろうという記事です。

作成する予定のもの

アンリアルクエスト(以降UQ5)に弓を射る、泳ぐ、馬に乗る、インベントリー機能を追加してトライアスロンで借り物競争をするようなゲームを作ろうと思っています。
これはオリンピックで話題になったトライアスロンと逃げ上手の若君というアニメで犬追い物のシーン見て竹を切って、弦になる麻と鳥の羽を回収して業者にもっていって、矢を手に入れて馬に乗って犬とか的(まと)に当てて点数を競うとか良さそうと思ったのが発端です。

UQ5をダウンロード

UQ5の模範解答の記事の一番下から模範解答サンプルプロジェクト 通常版をダウンロードします
「アンリアルクエスト5 ~剣を使って敵を倒そう!~」模範解答プロジェクトデータを公開!|株式会社ヒストリア (historia.co.jp)

このままだとVRM4Uというプラグインの最新のㇼターゲットの恩恵にあずかれないのでUE5.3でプロジェクトを開きます。(現在のVRM4Uはマテリアルやㇼターゲットの機能の関係でほぼUE5.2以降のサポートとなっている。)

弓を射る仕組みを実装

九里江めいくさんの以下のYoutube見て弓を射る箇所の実装をします。
【UE4/UE5ゲーム制作講座】ついに弓矢を0から実装するぞ【初心者向け】 (youtube.com)

UQ5に組み込むにあたり極み本のみで知識を得た人だと全然ステートマシンとか違うじゃんということで実装にだいぶ悩むと思うのですが、今回は弓を射るフラグが立ったらUQ5の動きを乗っ取ってMisamoでダウンロードしてmixamo_converterで変換した歩きながら弓を構えるポーズ(StandingDrawArrow_UE)に置き換えることにします。

弓を構えるポーズを混ぜる


まず、UQ5のメインプレイヤーのアニメーションBP「ABP_UQ5_Player」を検索して開きます。
MainStateのある所の左あたりに歩きながら弓を構えるポーズのアニメーションをドラッグします。既に九里江めいくさんの動画でisBowというフラグが作られているはずなのでUseCachedPose Mainのあたりに以下のようなBPを書きます。

弓を弾くモーションを無理やり混ぜる

Blend Pose By Bool という関数で弓フラグがTrueだと弓を構えるポーズが流れFalseだと元々の動きになります。
弓を射る箇所はどうなるかというとこの処理の前段階でDefaultSlotが組み込まれているのでアニメーションモンタージュを使うことにより勝手に動作するようになります。

サンプルにはモンタージュ再生の機能が既に実装されている

刀と弓切り替えるボタンを実装する

キーボードで弓モードの切り替えしてたのですが面倒です、今回UQ5にあった爆弾投げる処理は使わない予定なのでBボタンで弓と刀を切り替えるようにします。
(ROG ArrayだとゲームパッドモードではOKですがデスクトップモードでは今回の実装だけでは不十分ですが一旦は置いておいて次に行きます)

一応以下の場所でキーマップを確認できます。これにより今回書き換えるのはIA_Throwであることがわかります。

UQ5のインプットを確認
UQ5のキーマップを確認

では主人公のブループリント(BP_UQ5_Player)を開きIA_Throwを検索します。

投げるボタンを武器切り替えに変更

以下のように弓の出し入れをしていたところに追加します。
ピンを追加するときに▼を押してStartedを出してそこから繋ぐようにしてください。

テストプレイして弓モードに切り替えできることを確認します。

矢を放つモーションを追加する

今度はIA_Attackを検索して空中にいない状態の後ろでisBowフラグで処理を分岐するようにします。

矢を撃つ分岐

弓を右手のソケットに生成し、弓を射て矢をつがえるモンタージュを追加します。

九里江めいくさんの動画と違う点は、表示しているキャラクターに矢を発生させるソケットつけるところとモンタージュでモーションを流し込むのは元のUQ5のキャラクターであるところでしょうか。「メッシュからポーズをリターゲット」という機能を使っているのでモーションはUQ5のアニメーションを変換しながら使うのですが、矢の発生位置や弓を持つ位置はVroidの手の位置でなければおかしくなってしまうからです。

弓を持つソケットを作成
UQ5のプレイヤーの下の階層にVRMを配置する。

私がしたVRMのガワを使用するやり方は私の書いた以下の記事を参考にしてください。
UQ5.3にVroidを適用してみよう|デンオー (note.com)

上の階層のモーションを下の階層でもそのまま使う設定

前書いていた記事に勘違いしていたことがあって透明のマテリアルをセットしていましたがVisibility Based Anim Tick Optionの値をAlwaysTickPoseにすればレンダリングのVisibleをFalseにしても動作が伝わります。

コントローラーで弓が撃てるようになりました。

矢は撃てますが今のままではダメージを与えられないので矢の先にダメージを与える範囲を追加します。
(ダメージ与えるのは一応壁とポーンにだけ当たるようにしてます。)

以下のように通過時に当たったものに10ダメージ与えるみたいに実装します

泳ぐを実装する

次に九里江めいくさんの以下の動画を見て水の中を泳ぐ処理を実装します。こちらは極み本で教わるステートマシンの遷移そのままなので問題ないでしょう。
【UE4/UE5ゲーム制作講座】海で泳ぐ (youtube.com)

えっ?こんなことしないでも弓のモーションと同じ事すればいいじゃんって思うかもしれませんが多分それでも動きますが水の中に入ったフラグなどの処理の実装をここで語れば長くなってしまうし、バグ出ても解決するのが難しいので今回はそのままでいきます。
テストプレイして泳げるのを確認します、水中での攻撃とか採取も時間があれば実装したいと思います。

インベントリー用の関数を用意する

インベントリーのアイテム管理のためにST_Itemという名前で構造体を以下のように設定します。

今のところnameとcountしか使わないです

UQ5用のゲームモードにitemsという名前で配列の構造体を作ります。
デフォルト値でbanbooという値を作ります。
今回作るインベントリーはここに先に用意したキー名の物だけ数量を管理できるような仕様です

以下のようにitemsの中で指定したキーの個数と追加したい値を追加する関数を書きます。本当はREMOVEせずに値だけ上書きしたいのですが多分UE5.3だと今のところ一旦構造体から消して変更した状態の構造体を追加するしかできないようです。

採取用に壊れる竹を作成する

ゲームにクラフトの要素を追加するために竹のスタティックメッシュからブループリントを作成します。
壊れるようにカプセルコンポーネントを追加しコリジョンをPawnにします。

何らかのダメージを受けたときにイベントが発生するようにBiginPlayでUEで最初から予約されているOnTakeAnyDamage_EventをBindします。

次に3回ダメージを受けHPが0になったらインベントリーに指定のアイテムを追加する関数を呼んだ後にメッシュが消える処理を入れます。
余裕があったらここに数秒壊れたメッシュが出る処理を追加したいと思います。

テストプレイしてゲーム上で数がカウントされているのを確認します。

採取用にニワトリを作成する


今回犬追い物をやりたいというのがあるので有料コンテンツですがAnimal Pack URTRA の1と2を入れました。
とりあえずキャラクターでブループリントを作成しニワトリのメッシュとアニメーションブループリントを選択し保存します。

位置の調整のためカプセルコンポーネントのCapsule Half Heightをメモっておきます

メッシュの位置のZ軸に先ほどメモった値のマイナス値、回転のZ軸-90を入れます。

でこぼこの地面にスポーンする予定なので上空にスポーンするのでSimulate Physics(重力)のチェックをいれます。

とりあえず、羽を採取できるようにゲームモード内の変数itemsのデフォルト変数にfeatherを追加します。


先ほどの竹のブループリントをニワトリのブループリント内にコピーしダメージ受けたら羽が増える仕組みを追加します。
今回はパラメータで渡すkeyにfeatherを与えます。

マップに配置して刀でダメージ与えて羽が採取できることを確認します。


ニワトリが歩き回るようにする

ニワトリのキャラクターをAiで動かすときに回転が不自然にならないようにBPの詳細でuesで検索し「Use Controller Rotation Yaw」のチェックを外します。

また、rotateで検索して「Orient Rotation to Movement」チェックを付けます。

ブループリントの作成でaicで検索してAiコントローラーを選択し、選択を選びBP_AIC_Chikenという名前を付けます。

ニワトリのブループリントの詳細でAiで検索してAuto Possess AIをPlacedInWorldOrSpawnedに変更し、AI Controller Classを先ほど作ったAI Controller Classにしコンパイルし保存します。
これでニワトリをランダム位置にスポーンしてAiで動かす下地ができました

次にAiを作成します。まずBT_Chikenという名前でビヘイビアツリーを作ります。BB_Chikenとういう名前でブラックボードも作っておきます。

作成したビヘイビアツリーのBT_Chikenを開いてビヘイビアツリータブの詳細のBlackboard Assetに先ほど作成した「BB_Chiken」をセットします。


とりあえず中身はSequenceとWaitだけ作って保存します。

ブラックボードタブに移動し新規キーでObjedtを選択します。

値の方のEntry NameをTargetActorにしてKey Typeのタブを開いてBase ClassをActorを選択します。名前を変更するときEntory Nameの方をかえてはいけません、必ず左側の追加した方で変えましょう。UE5.3の場合どうやらビヘイビアツリーなどで名前が使用できず原因不明なエラーに苦しむことになる場合があります。

ビヘイビアツリーに戻ってシーケンスの下にmovetoを作ります。
Blackboard Keyの値にtargetActorを選ぶと近づいてきては5秒ごとに休むAiができている予定です。

とりあえずニワトリ用のAIコントローラー「BP_AIC_Chiken」を開いてBiginplayにRun Behavior Treeを選んでBT_Assetに先ほど作成したBT_Chekenを選択し保存します。

そうするとブラックボード用の変数が使えるようになるので出してSelfActorとTargetActorに以下のようにオブジェクトに対して値をセットします。

動かしたいレベルにの範囲にナビメッシュを配置します。

ニワトリも配置してテストプレイしニワトリが近づいてきたらとりあえず成功です。

次に移動前にジャンプするようにしたいのでビヘイビアツリーBT_Chekenを開いて新規タスクを作成でBTTasaku_Blueprintを選択し、BTT_Jumpという名前にします。

BTT_Jumpを開いてReceive Execute Ai関数をオーバーライドします.。
BeginPlayで全体で使う値を変数化したりイベントを受ける準備をするのビヘイビアツリー版だと考えると分かりやすいかもしれません。

以下のように実装してキャラクタームーベントの中のジャンプ関数を呼び出します。ジャンプした後のFinish Executeを忘れるとタスクが止まってしまいます。(Successのチェックをしないと次のタスクに行きません)
キャラクターをdestroyした時などCastに失敗した時もFinish ExecuteしないとAiが止まってしまうらしいのでこちらも忘れずに実装します。

ビヘイビアツリーに戻ってBTT_JUMPを追加します。

動作を確認します。問題なければビヘイビアツリーを左のように改造して再度テストします。

右側のブロックの追いかけるのシーケンスを右クリックしてCone Checkのデコレータを追加します

Cone CheckのブラックボードのCone OriginがSelfActor,ObservedがTargetActorになるように選択し保存しテストします。
視界に入ってから移動が始まれば成功です。

ニワトリが近づくまで何もしてこないのはあまりにもつまらないので、近くを散策するようにします。まず移動先の場所を格納するためのブラックボード変数を作ります。

ニワトリ用のAIの中に近くの移動先を取得するための関数を作ります。

ブラックボード参照してMovetoするだけならTickで回しても良いのですが多分重たいので別の方法をとります。
ちょっと前の工程で作ったBTT_JUMPを別名(BTT_Wonder)で保存し開き以下のように中身を書き換えます。要は先ほど作った関数がキャラクターのAiコントローラー内にあるのでキャストを駆使して呼び出してブラックボードにキャラクターの近くのランダムな位置を書き込んでいるのです。

ビヘイビアツリーの先頭にランダムに移動してちょっと停止する形に書き換えて実行してみます・。ニワトリがあちこちに動き出したら成功です。

この後、ニワトリが攻撃してしたのち逃げていくところを実装予定

馬に乗る

犬追物やるなら馬に乗ることが欠かせない気がするので、ここ2年以内にアンリアルエンジンを始めたユーザーのお財布にもやさしいAnimal Pack URTRA2の馬を使っていこうと思います。さすがに人のモーションとかないので雑な仕上がりですが、ぷちコン応募くらいならきっといけるでしょう。

ますは馬に乗るために足を開いた浮いているキャラが必要なのでManyの落ちる時のモーションMM_Fall_LoopをコピーしてMM_HorseRideという名前にします。(もちろん自前で用意してもいいです、新しいモーションを作成するというところで簡単な固定ポーズやループアニメーションを取得する方法書いているのでそちらも参考にしてください)

弓のモーションを入れたUQ5のアニメーションBPであるABP_UQ5_Playerを複写してABP_UQ5_Riderを作成します。
開いて、以下のように改造します。Lyered B;end by Boneは右の方にあるものをコピーして使います。

やりたい設定は以下の通りなのですが複写してもってきてあれば既に設定してあります。ひょっとしたら無駄な工程が混ざっているのかもしれません。

次にプレイヤーキャラであるBP_UQ5_Playerを複写してBP_UQ5_Riderを作成します。開いてスケルタルメッシュを追加してhorseという名前にしてSkeletal Mesh AssetにSK_horse_skeletonをセットします。
本当はソケットつけて座らせたいのですがUQ5のプレイヤーーキャラにC++で特殊な処理が入っていて馬の下に配置させると色々厄介なことになるので断念しました。

馬にのってるようにするためスケルタルメッシュを30ほど上にあげます。
本来一つ上の階層のMesh側でやりたいところですが馬が浮いてしまうためこの不法しかないようです。

これらのことをやっていると馬のアセットが悪いのか勝手に一番上の階層の設定が書き換わっているのでニワトリの最初の設定を参考にuesで検索し「Use Controller Rotation Yaw」のチェックを外し。otateで検索して「Orient Rotation to Movement」チェックを付けてください。
では作った馬をマップ上に配置してみましょう。

マップのレベルブループリントを開きます。

マップに配置した馬をレベルブループリントにドラッグし変数に昇格します。
レベルブループリントのBiginPlayに馬とプレーヤーキャラクタを変数に格納する処理を書きます。プレイヤーキャラであるBP_UQ5_Playerをキャストし変数に昇格しBasemanと名付けます。

Cキーを押したらプレイヤーと馬の操作が入れ替わるBPを書きます。


コンパイル、保存してテストプレイすると馬には乗れましたが馬が荒ぶる荷もほどがあります。なので馬のアニメーションBP(BP_Horse_AnimBlueprint)を複写してABP_RidingHorseを作り開きます。
ランダムにアニメーションを再生する設定になっているので新しいステートマシンを作成します。馬にもモンタージュで特別な動きをさせるかもしれないのでDefaultSlotは入れておきます。

新しいステートマシンとDefaultSlot

ステートマシンをダブルクリックして入って以下のような遷移を入れます。アニメーションは右のタブからドラッグすれば入ります矢印はアニメーション通しでドラッグすればいれられます。アニメーションの遷移の条件は矢印の横の丸をクリックすれば書けます。
アイドル状態でiswalkのフラグが立てば歩くアニメーション、isJumpフラグが立てばジャンプするようにします。

もちろんこのままではフラグが立たないのでBP_UQ5_Riderのイベントグラフで移動キーを押したときにisWalkフラグをたてジャンプしたときにはisJumpフラグが立つようにします。Jumpで立てたフラグはとりあえずdelayで1秒後に戻します。

馬にジャンプさせるためのフラグ管理

厳密にやりたかったら本体のメッシュ側のIsFallingを見て判断するのだと思います。

そもそも馬と人がくっついていれば何も問題がないので一応以下のように無理やりソケットアタッチしてもよいと思います。

アタッチする関数

ただ、実際馬が走らないとか左右に動いたときにモーションが物足りないとなってきたのでブレンドスペース作ります。この工程を人にまでやればUQ5ベースでなくて良くね?みたいにはなりますが、刀での攻撃モーションとかドッジロール入れるの面倒なのでまだまだ十分時短できてます。
ブレンドスペースですが、アニメーション→ブレンドスペースです。
極み本の実装だとレガシー→ブレンドスペース1Dです。
違いはスピードだけかスピードにプラスして左右を向くアニメーションがあればそれもブレンドしてくれるので今回みたく方向転換のアニメーションがそろっている場合は使うと便利です。

今回はAnimal_pack_ultra_2の方のスケルトンを選びます。
BS_Hourseと名付けた上で開きます。


水平軸をAngle 垂直面をSpeedとします。中央下のグラフに0,0はidle 0,100は歩行 0,400は走り -90,0は左旋回、90,0は右旋回のアニメーションになるようにアニメーションをドラッグして設置します。
設置したらCTALを押しながらマウスをグラフ内でドラッグしてアニメーションの遷移状態を確認します。

作ったブレンドスペースを馬のABP_RidingHorse内のステートマシンにドラッグして配置後ダブルクリックして中に入ります。

AngleとSpeedを変数に昇格します。

ステートマシンンの中身をこう書き換えます。

Speedについては騎乗した人のBPのイベントグラフで以下のようにセットします。

押してない場合走り続けてしまうため以下ようにCompleted時にSpeedを0にします。

Angleはマウスの左右で動かすのでこうですが、動きを見る限り0をセットし続けた方が無難かもしれません。

この状態で剣を振れますが。ソケットの位置がずれてますし、弓も撃つモーションは再生してますが矢も出なければ中心を表示するウェジットも出てません。それ以上に馬に乗り降りしているのに自分が見えたままというのもおかしいので姿の表示非表示を実装します。
まず、プレイヤーと刀の表示非表示の徒歩と騎乗の両方でカスタムイベントで関数を作ります。

騎乗している方のこの関数はイベントグラフのBeginPlayで呼び出すようにします。

騎乗する人の人は配置時には表示しない。


まず弓を構える時に出るウィジェットが表示されない問題ですが、プレイヤーキャラの入れ替えが行われたせいで入れ替えられた方のキャラクター側に元のキャラクターが作ったUIへのアクセスができなくなるためです。
なのでウィジェットを作る処理をBP_UQ5_GameModeのbeginplayに移植します。他からアクセスするので変数化を忘れないように。

次に元々ウィジェットの作成をしていた箇所でゲームモードのCrossHair変数を元々あったCrosshairの変数に格納する処理に書き換えます。

マップのレベルブループリントのキャラの切り替えのところに組み込んでみます。

こちらが馬に乗る時の物です。

こちらが馬から降りる時の処理です。
カスタムイベント化しておき、馬の乗っている状態で回避した時にも動作するように設定しておきます。
また、カスタムイベント化しておきジャンプして接触した時にも騎乗できるようにします。

馬を降りる時に馬に乗っていないキャラの位置を馬と同じにします。
プレイヤーの位置が馬の上で浮いているような位置にあるおかげで偶然にも飛び降りるような動作をしてくれます。

では今度はレベルブループリント上に馬に乗れる範囲に人が入ったら、飛んでる状態で馬に乗っている状態じゃなければという処理を書いて馬に乗る処理につなげます
馬に乗る範囲はBoxコリジョンでpawnのみをオーバーラップそれ以外無視で作ります。ついでに刀のソケットの位置も調整しておきましょう。

レベルブループリント上のBeginplay の延長上に以下のようなBindを作ります。
レベルブループリント上に

コンパイル後テストプレイしてジャンプで馬に接触したら馬に乗れることを確認します。

次に馬に乗っている状態でローリング(左SHIFT )で馬から離れるようにします。ブループリントインターフェイスでレベルの関数を呼び出せばと思っていたのですがうまくいかないので素直にゲームモード側に実装することにしました。

まずはレベルブループリントのBeginPlayで格納している変数をBP_UQ5_GameModeにも設定します。(先にBP_UQ5_GameMode側で変数を定義しておく必要があります。)

レベルブループリントから馬から降りる処理をBP_UQ5_GameModeに移植します。

回避処理のボタンを押された時に馬を降りる処理を呼び出すように変更します。


馬に乗った時に十字が出ないのは十字の出し入れが各pawnが管理しているせいなのでBP_UQ5_GameModeに以下のような関数を作って既存の箇所と入れ毛ます。

照準の十字を出し入れする

また、矢が出ないのは馬に乗った方は十字の位置を取得できなかったためなのでBP_UQ5_GameModeに移したcrosshereの関数から十字の位置をとるように書き換えたらちゃんと馬上でも矢が撃てるようになりました。

対応が不完全で馬に一度乗ったら二度と馬に乗れないバグが出たので、ついでに馬の乗り降りの部分をゲームモード側に変更し整理します。
レベルブループリント側はこんな感じ

馬に乗るためにイベントの登録

ゲームモード側はこんな感じです。

馬にのる
馬から降りる

各々コンパイル後保存してテストプレイして矢に切り替えた時に十字が出て矢もちゃんと狙った位置に飛ぶようになったことを確認します。 

VMCで新しいモーションを作成する

UQ5のモーション+弓だけではちょっと今回のお題である遊園地にはちょっと足りない気がするので、ハシゴを登るのとロープを滑っていくモーションを追加しようと思います。残念ながらMixsamoによっそうな物が無いのでVRM Posing Desktopという私の記事ではおなじみのソフトでやろうと思います
Steam:VRM Posing Desktop (steampowered.com)

まずインポートしたVRMのスケルトンを使ってアニメーションBPを作成します。とりあえず。APB_VRMPoseと名付け開きます。

はるべーさんのページそのままですがこうとしか書きようがないです。
既に同じPC内でVRM Posing Desktopでモーション撮る設定になっていますができれば別のPCのソフト入れてそのPCのIPv4を調べてServerAddressにIPV4アドレスを入れて送ってもらった状態でモーション作った方が良いです。
なぜならUEのエディタにフォーカスが当たっていないとキャラが動かないからです。
VRM Posing Desktopを起動し標準ポーズの右上の物を選び画面左上の編集ボタンを押します。

まず、おへそのあたりにある赤い点をクリックしてJ_Bip_C_Hipesの値を上から0,0,0,1にします。その後●動かして指を緩めに握ったりしてハシゴを登りそうなポーズにします。左右反転ボタンを押して切り替えてモーションとして使えそうだと思ったら左上のチェック委押します。


ポーズのウインドウの出し入れのボタンを押し、vma方式で保存します。

次に編集ボタンで編集に戻り左右反転してチェックし、名前を付けて保存します。
実は保存はしなくても実はいいのですがやり直しを防ぐために保存しておきましょう。
右下にあるモーションのループ設定を以下のようにすれば2秒かけてループアニメーションしてくれるようになります。

ポーズのパネルに隠れているVMCのアイコンを押します。


同じPCで作業している場合はそのままポーズ送信を押します。

UE5に戻りABP_VRMPoseを開くとループモーションが送信されています。

赤いボタンを押すとポーズ保存のダイアログボックスが出るので保存します。ポーズが何週かしたら停止ボタンを押し保存します。

使えるアニメーションが増えました。

NPCを作成する

SeaJet_chさんの以下の方の動画を参考に、ランダムに歩き回る人と、巡回地の周辺をランダムに歩く人を作成します。

【UE5】街中を歩き回るNPCを作ってみよう!【Create an NPC that roams the city!】【Navigation】【春日部つむぎのゲーム作ってみよう!】 (youtube.com)

NPCを作る時にはVRMをインポートする前にできたらサードパーソンのコンテンツを追加してそちらの方で上の動画の実装をしてください。
VRMのガワを付ける時にはSKで検索したVRMのスケルトンのコンパチブルスケルトンにサードパーソンのSK_Manequinをセットして

いつもの作ってIKRetargeter Assetに自動作成されたIKリターゲッター選択するのを忘れないこと。

配置して動きを確認します。狭い町に置くとしたら思ったより早いし、引っかかると思うのでと思うので徘徊する範囲は300くらいで狭めに歩くスピードも100くらいにしておいた方が良いっような気がします。

今回は特定の場所を巡回する鮭を作りたいと思っていたので巡回するNPCのベースに鮭のスケルタルメッシュとアニメーションをセットします。

泳ぐためにあらかじめ作っておいた海にキューブを3個沈め鮭を配置し書斎パネルのTarget Listの一覧に沈めたcubeをスポイトで選択します。

かなり巨大にしないと視認できませんでしたが一応は巡回してくれるようです。

NPCと会話する

基本九里江めいくさんの以下の動画のように実装します。

【UE4ゲーム制作講座】簡単な会話システムを作ってみる! - YouTube

違うところですが今回キャラクターの入れ替えがあるので会話システム自体なキャラクターでなくてゲームモードで実装します。
会話開始と会話終了のカスタムイベントを作ります。

ブループリントインターファイスでしゃべれるかとメッセージを取得する関数をひとつづつ実装する箇所は一緒です。

しゃべらせたいキャラクターにブループリントインターフェイスを追加し
Get_Talk_message関数にキャラクターのスポーン時に公開するメッセージ用の実装をするのは同じです。イベントなどでフラグを立てるなど特別な処理入れたり、複数の会話入れたい場合はここに実装します。

会話用のボタンが足りないのでアタックボタンを押したときに目の前にいるか判断し会話するように実装することにします。

自分の向いている方向のちょっと前にトレースの範囲を設定します。
ObjectTypekaからピン出してMakearrayを出しPawnのみを指定します

複数のものがHitする可能性があるのでForeachでループさせ先ほど実装したBPインターファイスでしゃべれるかをチェックししゃべれない場合はそのまま攻撃、しゃべれる場合は会話の処理を呼びだします

会話できるキャラがいない場合で会話中フラグが立ってない場合にのみ攻撃
会話できるアクターがいれば会話処理、可能であれば処理をBreak(ほぼ無理)

デバッグ用にDrawDebugTypeをForDurationにして実行してみると緑の球にに赤く点が出るところが確認できます。

しゃべっている時にこちらを向くというのを実装しようとしてましたが、Aimovotoの関数を途中でキャンセルしなきゃならないとかこのままでは無理なことを悟ったのでNPCの動作をニワトリでつくったものをベースに作り直すことにします。

ニワトリのAIコントローラーとブラックボードとビヘイビアツリーをコピーしてNPC用に名前を変えます。

複製して作ったビヘイビアツリーを開き、詳細パネルのBlackboard Assetを複製して作ったNPC用のブラックボードに設定し保存します。

複製して作ったNPC用のAIコントローラーを開きRunBehaviorTreeに先ほど保存したビヘイビアツリーをセットします。

レベルに配置してその辺を徘徊するようになったら成功です。
キャラにジャンプされても困るので、コーンチェックとジャンプはやめて自分が会話中かチェックし、会話中ならプレイヤーに近づくように改変します。ブラックボードにIsTalkというbool変数を追加します。

NPC用のAIコントローラー内に作ったブラックボード変数に値を入れるカスタムイベントを作ります。

会話のためのBPインターフェイスBPI_Talkにプレイヤー側を向くための関数LookPlayerを追加で定義します。使い易い様に入力にboolのフラグを付けます。

ゲームモード側の会話のカスタムイベントに以下のように追加します。

閉じる時がバグの温床のような気もしますが今はこのままいきます。
キャラクターのイベントグラフのインターフェイスにあるLookPlayer関数を以下のようにブラックバードのisTalkフラグの設定関数を呼び出すように実装します。

ビヘイビアツリーをブラックボードのIsTalkで判断するようにデコレーターを書き換えます。

この記事が気に入ったらサポートをしてみませんか?