UE4でとりあえず敵を出したり、弾を撃ったりする
はじめに
とりあえずハンズオン勉強会で習ったことの復習を兼ねた記事です。
シンプルな3Dアクションゲームを想定して作っていこうと思います。
UE4のガチ初心者なので、バッドノウハウとかあると思います。
手順や作業を整理して記事を書いてるわけではないので、拙い点はご容赦を。
プロジェクト的には↓を引き継いでます。
nmmn.hatenablog.com
HPやらなんやらがありますが、敵の追加と弾を撃つとかの実装は過去の記事とはあまり重複しないはずです。この記事だけ読んでも問題は無いかと思います。
何をやるのか
タイトルの通り、敵を実装します。
敵は弾を発射してくるようにして、自分を弾を発射できるようにして、やっつけたりやっつけられたりできるようにします。
全体観
少々見づらいですが、青い弾がプレイヤーから発射された弾。
赤い弾が敵から発射された弾です。
敵とかはBlenderかなんかで作ってぽいって実装できればかっこよかったのですが、Blenderが難しかった
ので諦めます……。
自分が弾を撃つ
自分が発射する弾を作る
まず自分で弾を発射できるようにします。
BP_PlayerBulletという名前でアクターのブループリントを作成し、球コリジョンに球コンポーネントを乗っけて、オマケにPointLightを乗っけてます(ライトは別に重要ではないです)。
デフォルトの状態だと球は物理演算の影響を受けて落ちちゃいます。
今回はPhysics>SimulatePhisicsのチェックボックスを外しておきましょう。
発射された後、飛んで行く部分はProjectileMovementを使いました。
このProjectileMovementのProjectile>InitialSpeed項目で発射された後の移動速度を制御します。
とりあえず1500くらいにしてみました。
自分で撃った球が自分にあたったりするとマヌケな事になったり、バグの元になったりするので、コリジョンプリセットをCustomにして、画像みたいにチェックします。
イベントグラフにはHit時の処理を作りましょう。
Hitした対象が自分であれば特に何もせずDestroyActorして、そうでない時はダメージを与えて爆発エフェクトをスポーンしてDestroyActorするようにしています。
球を発射するアクションをゲームに登録する
「球を発射する」というアクションを登録しないと球が発射されません。
今回はマウスクリックで球を発射できるようにします。
編集>プロジェクト設定から、インプット項目を選択してエンジン-インプット設定画面を開きます。
ActionMappingsのところの右の+ボタンをクリックして、新しいアクションを登録しましょう。
Jumpはもともと設定されてたアクションで、Fireが今回新しく作成したアクションです。マウスの左ボタンが押された時、Fireイベントが発火するようにします。
プレイヤーキャラに球の実装を行う
何はともあれ球の発射地点を作ります。
わかりやすさのためメタリックなSphereをテキトウに配置して、その部分にFirePontというArrowコンポーネントを作成せいました。
このSphere(Arrow)から球を出そうって寸法です。
余談:本当はモーションを銃をもってるやつに変更して、銃を持たせてそこから球を出したかったのですが、うまくできなかったのでこの記事では触れないことにしました(´・ω・`)
ThirdPersonCharacterのイベントグラフに、Fireイベントに関する処理を作りましょう。画面外のところでは前回の記事で作ったノードやらなんやらがあります。
Fireインプットアクションが起きた時、FirePointの一を取得して、SpawnActorノードでBP_PlayerBulletアクターを出現させます。
敵が弾を撃つ
敵の弾を作る
BP_PlayerBulletを複製して敵の弾を作ります。BP_EnemyBulletという名前にしました。
基本的にはBP_PlayerBulletと変わりませんが、今回は何にあたっても同じ処理でよいので、コリジョンプリセットをBlockAllDynamicに変更します。
Hit時のイベントグラフを少しだけ組み換えます。
ThirdPersonCharacterにHitした時ApplyDamageノードにつなぎ、爆発エフェクトを発生させます。それ以外の時は爆発エフェクトを表示してそのまま消えるようにします。
敵を作る
敵の弾を作ったので、いよいよ敵を作りましょう。
球とシリンダーを組み合わせて、シリンダーのStaticMeshをTubeにしていい感じにしました。
敵は一定範囲にプレイヤーが居るとプレイヤーの方に向いて、一定間隔で弾を発射するようにします。
敵の感知範囲として、ActiveAreaという名前の球コリジョンを作成しました。
敵のイベントグラフはなかなかハードです。
一つづつ作っていきましょう。
比較的シンプルなやつから作ります。
IsActiveというBoolean型の変数を作ります。
この変数を使ってプレイヤーを攻撃する状態と、アイドル状態との切り替えを制御します。
イベントティックを使って常に状態を更新できるようにします。
IsActive変数がTrueの時、SetWorldRotationノードを使ってプレイヤーの方へ向くようにします。
ターゲットには敵自身のコンポーネント、向く方向はプレイヤーと敵のLocationから作成した、FindLookatRotationノードをつなげます。
(このノードすごいですね。プログラミングで実装しようとすると、数学の知識も必要だし結構面倒な所だと思います)
Shootイベントを作成しましょう。
プレイヤーの弾を発射する処理とほぼ同じですが、ブランチノードを使ってIsActiveの時だけShootイベントが行われるようにします。
ActiveArea内にいる時、IsActive変数がTrueに、そうでない時はFalseになるようにします。落ちる床の処理と同じように、OnComponentBeginOverlapとOnComponentEndOverlapノードを使って処理します。
SetTimerbyFunctionNameとClearTimebyHandleノードを使って、Shootイベントが定期的に呼ばれるのを実現しています。
AtackModeカスタムイベントは後で出てきます。
初期化処理は煩雑になってしまいましたが、日本語にすると簡単です。
まず、開始時に有効範囲の値をセットします。
その後、プレイヤーと自分の距離を計算し、その距離が有効範囲内だった時、IsActiveをTrueにします。
どうしてこの処理を作ったかというと、ゲーム開始時にプレイヤーが最初から有効範囲内にいた時、IsActive変数Trueにならなかったからです。
どうやらゲーム開始時に最初から範囲内に対象がいる時は、OnComponentBeginOverlapイベントは発火しないようです(名前でもそんな感じしてますね)。別のイベントを採用するなどして回避もできそうですが、今回は処理を作ってしまいました。
BeginPlayノードからSetSphereRadiusノードで、ActiveAreaにActiveRadiusの値をセットします。
プレイヤーと敵の距離計算はVectorLengthノードで実装しました。
プログラミングのみで実装しようとするとVector3とVector3のベクトルを引き算して……とかやらないといけないところを、たったこれだけのノードで、しかもプログラミングなしに実装できるってとんでもないことですね!
VectorLengthとActiveRadiusの値を比較して、ActiveRadiusより小さければIsActive変数をTrueにして、攻撃を行うロジックにつなげます。これをAtackModeイベントを作り、Shootのところにつなげることで表現しています。
おしまい!!
今回は作ったものが複雑になった上に、量も多くて一日空いてしまいました。
アイテムの実装もしようかと思いましたが、HPのあたりやOnComponentBeginOverlap等ですぐ実装できることので、記事にするのは辞めました。
わかってないこと、疑問点、懸念事項
- 銃を持つモーションに切り替えようと思ったが、うまくできなかった。
- MovementComponentを探すのに手間がかかった。
ひとまずこの記事で、UE4ハンズオン勉強会で教えてもらったことはだいたいおわりです。
それにしてもUE4はすごいですね、。本来であれば数学とプログラミング言語の知識があって始めてスタートラインに立てて、その後えっちらおっちら苦労してプログラミングしてゲームを作成して……とやって、この程度のゲームを作るのにもそれなりのコストがかかるところを、勉強会では2日でやってしまいました。
いちど教えてもらって作業をしたとはいえ、再現するのに随分と時間がかかってしまいましたが、UE4を扱うのは楽しいですし、これからも触っていきたいですね。
これでUE4の記事は一区切りです。
では、また。