UnrealEngine奮闘記

アンリアルエンジンでの開発やTIPSをまとめたblogです

インベーダーゲームを作る その5弾と当たり判定

今回は弾と当たり判定です。

  • 基底弾クラスの作成
  • プレイヤーと敵の弾クラス作成(派生クラス)
  • 弾Actorを生成する
  • メッシュにコリジョンを設定する
  • コリジョンのタイプ指定
  • 弾Actorの削除

基底弾クラスの作成

まず弾ですが、上に飛ぶプレイヤー用弾と下に飛ぶ敵用弾の2種類が必要になります。
2つ用意しても良いのですが、今回はクラスの継承を利用したいと思います。

まず弾モデルを作成します。
modesのGeometryからCylinderを選び、半径に5、Zに30を指定します。
その後、例によってStatic Meshとして保存します。
これをプレイヤー用と敵用2種類用意します。
(PlayerBulletMesh, EnemyBulletMesh)
※見分けが付かないので、片方は円すいにした方が良いかもしれません。色の設定は次回やります。
次にクラスですが、今回はActorを継承して「BulletBlueprint」という名前で作ります。
継承を前提とするためコンポーネントはSceneだけ作ります。StaticMeshは"設定しません"

Blueprintに移り、左にある「+Funcsionアイコン」を押し、新しい関数を作成します。
関数名は「MoveBullet」とし、Inputs(引数)は
Vector(MoveVector)とFloat(DeltaTime)の2つ用意します。

f:id:swiftnest:20140428175850j:plain:w460

弾の移動ですが、これは前回の敵の移動と殆ど同じです。
DeltaTimeとMoveVectorを掛け算し、自分のLocationに足し込むだけです。
これで弾の基礎となるクラスの完成です。

f:id:swiftnest:20140428180035j:plain:w460

プレイヤーと敵の弾クラス作成(派生クラス)

次にプレイヤーの弾クラスを作成します。

この際に注意するのは、Actorを継承するのではなく、BulletBlueprintを継承して作成します。
Classを作成する際、一番下に「Custom Classes」という欄があるので、そこを開いて「BulletBlueprint」で検索すると継承することが出来ます。

f:id:swiftnest:20140428232311j:plain:w460

次にコンポーネントですが、先程基底クラスであるBulletBlueprintでSceneを追加したので
今回はメッシュ(PlayerBulletMesh)だけ追加します。

f:id:swiftnest:20140428180158j:plain:w460
※今回は判りやすいようにマテリアルを設定してます

最後にBlueprintですが、Event Tickから初めて「MoveBullet」に接続するだけです。
引数のMoveVectorには(0,0,200)を入力します。

これでプレイヤーの弾が完成しました。

f:id:swiftnest:20140428180253j:plain:w460

同じ様に敵の弾も作成します。
違いはメッシュが「EnemyBulletMesh」だという事と
引数のMoveVectorに(0,0,-200)を指定する事だけです。

試しにレベルに2種類の弾を配置してみます。
Playを押すとプレイヤーの弾は上へ、敵の弾は下へ移動すれば問題ありません。

弾Actorを生成する

次はプレイヤーが弾を撃つようにします。

PlayerBlueprintを開き、「Left Mouse Button」からスタートします。
「Spawn Actor Class」を作成し、引数のClassにPlayerBulletBlueprintを指定します。
発射位置はプレイヤーの少し上なので、自分の座標にVector(0,0,30)を足して指定します。

これで左クリックすると弾が発射すると思います。

f:id:swiftnest:20140428232801j:plain:w460
※流れが複数ある場合は、右クリックメニューにあるCreate Commentでまとめると見やすくなります。

メッシュにコリジョンを設定する

後は当たり判定と爆発を作成します。

まずエディタ左側のコンテンツブラウザ内にあるPlayerMeshをダブルクリックします。
するとStatic Mesh Editorが起動します。
次にメニュー -> Collision -> 6DOPを選びます。

f:id:swiftnest:20140428231104j:plain:w460

これでボックス型のコリジョンが作成されました。

正しくコリジョンが作成されてるかどうかは画面上部アイコンの「WrireFrame」「Collision」をクリックすると判りやすいです。

f:id:swiftnest:20140428181549j:plain:w460

コリジョンのタイプ指定

次はコリジョンタイプの指定です。
やはりコンテントブラウザからPlayerBlueprintを選び、ダブルクリックします。

コンポーネントのStatic Meshを選ぶと、Detailsの中にCollisonがあります。
ここで今回はOverlapAllDynamicを選びます。
これは、敵の弾は敵自身を弾をすり抜ける様なコリジョンにしたい為です。

f:id:swiftnest:20140429005132j:plain:w460

同じ手順でEnemyMesh、PlayerBulletMesh、EnemyBulletMeshにも6DOPのコリジョンを作成し、PlayerBlueprint、PlayerBulletBlueprint、EnemyBulletBlueprintのコリジョンをOverlapAllDynamicにします。

そしてEnemyBlueprintに弾が当たった処理を追加します。
まずOn Actor Begin Overlapと、Spawn Classを追加します。classにはexplotionを、座標には自分の座標を指定します。
その後Destroy Actorを呼び、自分自身を削除します。

f:id:swiftnest:20140429004457j:plain:w460

PlayerBlueprintにも同じ処理を書きますが、Destroy Actorを呼ぶと進行不能になるので気をつけて下さい。

閑話休題-Collisionについて
今回は敵の弾は敵や弾をすり抜ける様なコリジョンにしたいため、OverlapAllDynamicにしましたが、物理的な弾にしたい場合はCollisionは「BlockAllDynamic」にし、Set Actor LocationのSweepにチェックを入れます。するとEvent Hitで当たった位置や法線方向が判るため便利です。

弾Actorの削除

最後に弾が画面外へ移動した時に消滅するようにします。

これは、敵が反転移動する処理とほぼ同じです。

f:id:swiftnest:20140429010003j:plain:w460

これでインベーダーゲームの基本が出来ました。

f:id:swiftnest:20140428182531j:plain:w460

ただし、現状では敵が攻撃しません。
腕に自身のある方は、是非チャレンジしてみて下さい。
参考までに私が作ったBPを以下にアップします。
ポイントは弾を撃つ為のタイマー(float ShotTimer)です。

敵のメインBlueprint
f:id:swiftnest:20140429015606j:plain:w460
移動反転関数ReverseDirection
f:id:swiftnest:20140429015645j:plain:w460
弾を撃つ関数ShotBullet
f:id:swiftnest:20140429014741j:plain:w460

次回は背景とマテリアルを修正して、見栄えを良くしたいと思います。

おまけ
Q.何故か弾が当たりません。
A.コリジョンが正しく設定されて無い可能性があります。
Play中に画面上部のポーズアイコンを押し、そのすこし右にあるEjectアイコンを押して下さい。
カメラがプレイヤーから切り離されるので、その状況でビュー画面の上にある「Lit」を「PlayerCollision」に変更して下さい。
コリジョンがあるものはピンク。無いものはグリーンで表示されます。
f:id:swiftnest:20140429012355j:plain:w460

追記

関数の作り方は大きく分けて2つ有ります。
1つ目はEventgraphなどの命令を選択して、右クリックメニューから「Collapse to Function」で作成する方法です。
f:id:swiftnest:20140606232235j:plain:w460
この場合、関数の末端には引数無しの「ReturnNode」が作成されます。
f:id:swiftnest:20140606232253j:plain:w460
もう一つの方法は記事にも有る「+Funcsionアイコン」を押して作成する方法です。
この方法で作成した場合は「ReturnNode」は作成されません。
f:id:swiftnest:20140606232301j:plain:w460
しかし、どちらの方法で作成しても実行結果は変わりませんし「ReturnNode」に接続しなくても結果は変わりません。
つまり、引数無しの「ReturnNode」は有っても無くても同じという事となります。