🐣

テンプレ通りのゲーム制作 FPS⑥アクタの生成と継承

2024/11/25に公開

アクタをレベル内に一定時間ごと発生させる

前回破壊可能なアクタを破壊し、スコア加算し表示しました。ただ、キューブを全部破壊してしまうと破壊すべきターゲットが無くなってしまうのでやることが無くなってしまいます。今回は破壊可能なターゲットを新たに供給していく仕組みを作ります。また、破壊可能なターゲットの種類を増やすために「継承」という仕組みを扱っていきます。前回の記事は以下の通りです。

https://zenn.dev/yukumoto/articles/b388daaa6a7939

まずはアクタを発生させるアクタを作っていきます。
コンテンツ/Blueprintsの階層に移り、右クリックしてブループリントクラスを作ります。

親クラスを聞かれますので下段の「すべてのクラス」の検索ボックスに「targetpoint」と入力してTargetPointを選びます。名前を「BP_SpawnPoint」にします。

作成したブループリントクラスを開きます。TargetPointクラスを継承しましたのでビューポートを見てみると、コンポーネントとしてスプライトコンポーネントという実体をもたずレンダリングされない目印のようなものが存在します。イベントグラフに移り、BeginPlayノード以外の半透明のノードは削除しておきます。BeginPlayノードからワイヤを伸ばしてSet Timer by Eventノードを作ります。Timeというスロットがありますので5.0を入れておきます。このノードは一定時間ごとにイベントを呼び出すことができます。Loopingの項目はチェックを入れます。これで5秒ごとに今は何もつないでいませんがイベントを呼び出します。

次に左下に以前扱ったカスタムイベントを作ります。空いている場所で右クリックしてAdd Custom Eventを選びます。名前を「Spawn」にしましょう。Spawnカスタムノードを作ったらそこからSpawn Actor from Classノードを検索して作ります。

Spawn Actor from ClassノードのClassの項目に「BP_Target」を選びます。スポーンとは日本語で「産卵」を意味します。カエルや鮭が卵を産むアレですね。FPSゲームなどで「リスポーン」という言葉がありますのでそれをイメージしていただけると良いでしょう。TransFormピンにGet Actor TransFormをつなぎます。最終的なノードは以下のようになっているはずです。

ノードを作り終えたらレベルエディタで作ったBP_SpawnPointをドラッグします。プレイヤースタート近くに配置しましょう。今回はX=1500,Y=1300,Z=300に配置しました。

これで再生してみましょう。

ボックスが空中から現れるようになった!

発生場所のランダム化

ボックスは発生するようになりましたが同じ場所からずっと出ているので待っていれば破壊できます。これでは若干単調なのでターゲットポイントを中心にランダムな場所から発生するようにします。

コンポーネントパネルの追加ボタンを押して「box」と入力して検索し、Box Collisionを追加します。名前は「Box」のままで構いません。

詳細パネルで位置をX=0,Y=0,Z=300にします。大きさの指定であるBox Extentの項目をX=1000,Y=1000,Z=300にします。

レベルエディタに切り替えて、コンポーネントパネルからBoxをドラッグアンドドロップします。

SpawnActor BP_TargetノードのSpawn TransFormに繋がっているGet Actor TransFormを削除します。TransFormピンを右クリックして「構造体ピンを分解」を選びます。TransFormという情報は「位置(Location)」、「回転(Rotation)」、「拡大率(Scale)」の3つの情報を一体化したデータ形式です。これを分解することでそれぞれの情報にアクセスすることができます。

分解したらSpawn Transform Location のピンから左にワイヤを伸ばしRandom Point in Bounding Boxノードを作ります。このノードはCenterを中心にHalf Sizeの指定した容積の中のランダムな1点の位置情報を返します。

Boxのノードからワイヤを伸ばし上段にGet World Locationノードを作りそのあとにRandom Point in Bounding BoxのCenterピンにつなぎます。これはBoxの中心を求めています。Boxのノードからもう一つワイヤを伸ばしGet Box Extentノードをつないでさらにその出力ピンからHalf sizeピンにつなぎます。これはBoxの大きさを求めています。

最終的に以下の画像のようなブループリントになるはずです。確認しやすいようにスポーン速度を1.0秒ごとに早めています。

これで準備が整いましたので再生してみましょう。いろんな発生場所からキューブが降ってきます。放っておくとステージ中キューブだらけになりますね!


キューブがランダムに降ってくる!

コリジョンプリセットを設定する

キューブが降ってくるようになったのですが、気が付いたでしょうか?弾を乱射していると空中に見えない壁が存在するのが分かります。弾が跳ね返ってしまいますね。

これはターゲットを発生させるBoxCollisionのコリジョンプリセット(衝突設定)が弾をはじくように設定されているからです。アクタとアクタが衝突する時、それぞれにコリジョンプリセットが存在していて、衝突したときのふるまいがコリジョンプリセットの設定に書かれています。BP_SpawnPointを開いてください。コンポーネントパネルで「Box」を選んで詳細パネルの中の「コリジョン」項目に注目します。おそらくコリジョンプリセットに「OverlapAllDynamic」が選ばれていると思います。これを覚えておいてください。これは「物理オブジェクトは全てオーバーラップして通過させる」という設定になります。
OverlapAllDynamic
この設定を変えていきます。上部メニューの編集/プロジェクト設定を選びます。

エンジンカテゴリの「コリジョン」を選びます。

プリセットを開き目的の「OverlapAllDynamic」をダブルクリックします。

開くと「OverlapAllDynamic設定のオブジェクトに当たってくる各設定のオブジェクトに対する反応」の一覧が表示されます。これは衝突してくる相手がどのような種類かで対応する反応を表示しています。注目すべきは一番下の「Projectile(発射体)」の部分です。つまり、現在はガンの発射体である弾丸に対して衝突してきたら「ブロック」するという設定になっています。これを「オーバーラップ」に変更してください。チェックを入れなおしたら承認ボタンを押します。

変更が出来たらもう一度テストしてみてください。問題なくブロックのスポーンエリアを通過できたはずです。このコリジョンプリセットというのは当たり判定を取るうえで重要な要素です。アクタとアクタが通り抜けてしまうもしくはブロックされる場合はこのコリジョンプリセットの内容を確認しましょう。

ターゲットを継承してバリエーションを追加する

さて、現在ターゲットは金色のボックスの1種類ですが今後は種類を増やしていきます。そのために「継承」という仕組みを使っていきます。
/コンテンツ/Blueprints/BP_Targetを親クラスとします。
「継承」とは親クラスの持っている機能はそのままにして、その上に違う機能を付加してバリエーションを作る事を言います。名前をわかりやすくするためにBP_TargetBaseにしておきます。このこと自体にはあまり意味はありませんが、どれが親クラスBPかわかりやすくしておくといいでしょう。
名前をBP_TargetBaseにします
親クラスの「BP_TargetBase」を右クリックして子ブループリントクラスを作成します。名前を「BP_TargetFloating」にします。


親クラスを継承して子クラスが作成された
作成した子クラスを開きコンポーネントパネルからStaticMeshを選択します。詳細パネルに移り、検索ボックスに「Gravity」と入力し、「EnableGravity」をFalseにします。

現在親クラスをスポーンしているBP_SpawnPointですが、子クラスをスポーンするように改変します。BP_SpawnPointを開き、イベントグラフをアクティブにします。SpawnActorノードのClassの部分のプルダウンを開き、「BP_TargetFloating」に選び直します。

これでプログラムを走らせてみましょう。

空中にボックスが浮かぶように
空中に浮かぶようになりました。偶然スポーン場所が他のオブジェクトと重なった場合ははじけ飛ぶこともあります。

プレイヤーの方向に向ける

現在、スポーン時には向いている方向が皆同じになっています。これをプレイヤーの方向に向けてみましょう。BP_SpawnPointで作業を続けます。現在クラスのインスタンスを発生させるSpawnActorノードは位置を指定するLocationしか指定していません。これに回転角度であるRotationも指定するようにします。Spawn Transform Rotationのピンから左にワイヤを伸ばし、Find Look at Rotationノードを作ります。このノードはあるアクタからあるアクタまでの回転角度を求めるノードです。

このノードを作ったらさらに左のStartピンに上部のRandom Point~のReturnValueとつなぎます(下の画像参照)。さらにTargetピンにはGetPlayerPawnからGetActorlocationとつなぎ、Targetピンと接続します。最終的には下の画像のようになります。これでプログラムを再生するとボックス発生時にプレイヤーの方向を向くはずです。

プレイヤーの方を向くようになった

プレイヤーの方向に飛ばす

さらに発生したボックスを発生と同時にプレイヤーの方向に飛ばしましょう。ボックスはふわふわ浮いていますが物理オブジェクトになっています。これを飛ばすには「AddImpulse」します。Impulseとは衝撃のことなので衝撃を加えるという事になりますね。SpawnActorノードのReturnValueからワイヤを伸ばしてAddImpulse(StaticMesh)ノードを作ります。

作ったAddImpulseノードに必要な情報を追加していきます。まず最初にVel Changeという部分のチェックを入れます。次にImpulseピンに衝撃の方向と強さを指定します。StaticMeshからGet Forword Vectorノードを作ります。これは「前方向のベクトル」を求めるノードです。発生したボックスの前方向のベクトルを求めます。次にGet Forword Vectorノードからワイヤを伸ばしてテンキーなどで「*」キーを押します。ベクトルの掛け算を行います。XYZに1000.0を入れておきます。最後にAddImpulseのImpulseピンにつなぎます。

再生する前にもう一つ設定しておきます。「BP_TargetFloating」を開いてクラスのデフォルトボタンを押し、「lifespan」と検索してInitial Life Span10.0にします。これはボックスの生存時間を10秒にしています。これを設定しないと発生したボックスがどんどん浮遊してかなりの数になるからです。

再生してみましょう。

次々とプレイヤーに襲いかかる!
プレイヤーの方に向かって次々と飛んでくるようになった筈です。これでかなりゲームっぽくなってきましたね。次は飛んできたボックスに当たるとダメージを受けるように設定していきます。お楽しみに!

Discussion