【Unity】FPSで弾を発射し、あたり判定を検知する方法
今回は大きく2部に分けてFPSにおける銃弾の発射、あたり判定について書いていきます。
本記事の内容は以下の通りです。
〇FPS視点で銃から弾を発射させる方法
- プレーヤーをつくる
- 銃を用意する(UnityAssetStoreのフリーアセット)
- FPS視点をつくりだす
- 弾を発射する
- 照準器をつくる
〇あたり判定を分ける方法
- 下準備
- あたり判定の使いわけ
- 試し打ち
銃から弾を発射させる方法
プレイヤーをつくる
まずは下準備として銃を撃つプレイヤーをつくっていきます。
Hierarchy→Create→3D Object→Plane Planeの名前を「Ground」にし、地面をつくっていきます。
色はMaterialを使用して好きな色を付けてください。
Scaleはお好きな大きさに設定してください。
Hierarchy→Create→Create Empty の手順で新しくフォルダを作成してください。
名前を「Player」に変更してください。
Positionを「Ground」より上に来るように配置しておきましょう。
銃を用意する
次に銃を配置していきます。
お好きな銃のモデルをUnityのアセットストア等でプロジェクトにインポートしてください。
インポートが完了したら、銃のファイルをHierarchyエリアにドラッグ&ドロップしてください。名前を「Gun」に変更してください。
このままだと「Gun」が「Ground」に埋まってしまっているのでPositionのY軸座標を調整して任意の高さに変更してください。Scaleはお好きな値に設定してください。
FPS視点を作り出す
「Main Camera」の名前を「FPS Camera」に変更して下さい。
「FPS Camera」のPositionを一人称視点になるように調整してください。
銃のPositionが( X : 0 ,Y : 2 ,Z : 0 )の時
「FPS Camera」のPositionを( X :-0.5 ,Y : 2.5 ,Z : -1.15 )に設定すると上記の画像のようになります。この場合、右利きの視点になります。
次に「FPS Camera」を「Player」の子オブジェクトにしてください。
続いて「Gun」を「FPS Camera」の子オブジェクトにしてください。
マウスの動きとカメラを連動させる
狙いを定められるようにマウス操作とFPS Cameraを連動させていきます。
Project→Create→C#Script を選択し名前を「CameraController」とします。
以下のコードを入力してください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
using System.Collections; using System.Collections.Generic; using UnityEngine; namespace FPS{ public class CameraController : MonoBehaviour { [Range(0.1f, 10f)] //カメラ感度、数値が大きいほどより直感的な操作が可能. public float lookSensitivity = 5f; [Range(0.1f, 1f)] //数値が大きいほどカメラが向きたい方向に向くまでの時間が長くなる. public float lookSmooth = 0.1f; public Vector2 MinMaxAngle = new Vector2(-65, 65); private float yRot; private float xRot; private float currentYRot; private float currentXRot; private float yRotVelocity; private float xRotVelocity; void Update() { yRot += Input.GetAxis("Mouse X") * lookSensitivity; //マウスの移動. xRot -= Input.GetAxis("Mouse Y") * lookSensitivity; //マウスの移動. xRot = Mathf.Clamp(xRot, MinMaxAngle.x, MinMaxAngle.y);//上下の角度移動の最大、最小. currentXRot = Mathf.SmoothDamp(currentXRot, xRot, ref xRotVelocity, lookSmooth); currentYRot = Mathf.SmoothDamp(currentYRot, yRot, ref yRotVelocity, lookSmooth); transform.rotation = Quaternion.Euler(currentXRot, currentYRot, 0); } } } |
入力が完了したら、「CameraController」スクリプトを「FPS Camera」にドラッグ&ドロップしてください。
下記の画像の個所を調整することでカメラの感度を変更できます。
マウスを動かした方向にカメラが動けば成功です。
*動作していることをわかりやすくするために「Ground」の四つ角にそれぞれ色違いのCubeを配置しています。
FPSらしくなってきましたね。
弾を発射する
いよいよ射撃のオブジェクトの作成に入ります。
「Player」が「Gun」をうてるようにしていきます。搭載する機能としては「連射機能」と「リロード機能」です。
Project→Create→C#Script を選択し名前を「Shooting」とします。
以下のコードを入力してください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Shooting : MonoBehaviour { public GameObject bulletPrefab; public float shotSpeed; public int shotCount = 30; private float shotInterval; void Update() { if (Input.GetKey(KeyCode.Mouse0)) { shotInterval += 1; if (shotInterval % 5 == 0 && shotCount > 0) { shotCount -= 1; GameObject bullet = (GameObject)Instantiate(bulletPrefab, transform.position, Quaternion.Euler(transform.parent.eulerAngles.x, transform.parent.eulerAngles.y, 0)); Rigidbody bulletRb = bullet.GetComponent<Rigidbody>(); bulletRb.AddForce(transform.forward * shotSpeed); //射撃されてから3秒後に銃弾のオブジェクトを破壊する. Destroy(bullet, 3.0f); } } else if (Input.GetKeyDown(KeyCode.R)) { shotCount = 30; } } } |
次にHierarchy→Create→Create Emptyで新しくオブジェクトをつくり名前を「Shooting」に変更してください。
Positionを「Gun」オブジェクトの銃口の少し前に設定しましょう。
「Shooting」スクリプトを「Shooting」オブジェクトにドラッグ&ドロップしてください。
そのあと「Shooting」オブジェクトを「Gun」の子オブジェクトにしてください。
「ShotCount」が弾倉に込められる弾数、「ShotSpeed」が弾速を表しています。
お好きな値で設定してください。
弾薬をつくる
Unityのアセットストアにも弾薬のアセットがたくさん存在するので、興味がある方はそちらでも構いません。
今回はSphereを用います。
Hierarchy→Create→3D Object→Sphereの手順でSphereを作成し、名前を「Shell」に変更してください。
Position、Scale、は自由に設定してください。
Shell→Add Component→Physics→Rigidbodyと設定してください。その際に“Use Gravity”を解除しておくと、弾の勢いが減衰することなくまっすぐ飛ぶようになります。
そのあと、「Shell」をPrefab化します。
Project→Create→Folderを選択しフォルダ名を「Prefab」とします。
「Prefab」フォルダに「Shell」をドラッグ&ドロップします。
「Shell」のPrefab化が完了したらHierarchyエリアのShellは削除します。
次に「Gun」の子オブジェクトの「Shooting」をクリックしてください。
先ほどPrefab化した「Shell」を「Bullet Prefab」にドラッグ&ドロップしてください。
ついに銃弾を撃てるようになりました。
再生ボタンを押して試してみましょう。
左クリックで射撃、「R」でリロード(弾の補充)ができたら成功です。
照準器をつける
以上の設定で様々な方向に銃を撃てるようにはなりましたが、狙いをうまく定められません。そこで画面上に照準器を表示していきます。
Hierarchy→Create→UI→Imageを作成しImageの名前を「AimAssist」に変更してください。
次にお好きな照準器の画像をUnityにインポートしてください。
使用する照準器の画像を選択し、Inspectorエリアの“Texture Type”を変更します。
上記の画像のように“Sprite(2D and UI)”を選択してください。
選択ができたらどこでもいいので余白をクリックしてください。すると下記の画像が表記されるので“Apply”をクリックしてください。
ここまでの設定が完了したらまず「AimAssist」をクリックしInspectorエリアを表示してください。
カーソルの画像をInsapectorエリアのSource Imageにドラッグ&ドロップしてください。
Inspectorエリア上部で照準器の大きさや位置を任意で変更してください。
*銃弾が照準器の真ん中に飛んでいくように微調整すると狙った個所に飛んでいくようになります。
敵のあたり判定を分ける方法
下準備
Hierarchy→Create→3DObjectから
Sphere ×1 名前を「Head」に変更。
Cube ×1 名前を「Body」に変更。
Cylinder ×4 それぞれ名前を「Right_Arm」「Left_Arm」「Right_Leg」「Left_Leg」に変更。
それぞれのTransformを任意の値で調整し、人型になるように配置します。
HierarchyエリアでCreate Emptyを選択し名前を「Enemy」に変更してください。
「Head」「Body」「Right_Arm」「Left_Arm」「Right_Leg」「Left_Leg」オブジェクトを「Enemy」の子オブジェクトにしてください。
あたり判定の使いわけ
このまま銃弾を「Enemy」に当てたとしても
このように弾が反射してしまいます。
ここであたり判定が必要になってきます。
「Enemy」にHPをつける
まず下準備として「Enemy」のHP設定をつくっていきます。
Project→Create→C#Script を選択し名前を「HP」とします。
以下のコードを入力してください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
using System.Collections; using System.Collections.Generic; using UnityEngine; public class HP : MonoBehaviour { public int hitPoint = 100; //HP // Update is called once per frame void Update () { //HPが0になったときに敵を破壊する if (hitPoint <= 0) { Destroy(gameObject); } } //ダメージを受け取ってHPを減らす関数 public void Damage(int damage) { //受け取ったダメージ分HPを減らす hitPoint -= damage; } } |
「Shell」が「Enemy」にあたった際に、「HP」すなわち体力が減り、0になった時にオブジェクトが破壊されるように設定されています。
入力が完了したら「HP」スクリプトを「Enemy」オブジェクトにドラッグ&ドロップしてください。
「HP」はお好きな値で設定してください。
ダメージ量を体の部位によって変える
銃弾、すなわち「Shell」が敵オブジェクトにあたった際に破壊(Destroy)される仕様を作成していきます。
Project→Create→C#Script を選択し名前を「DestroyObject」とします。
以下のコードを入力してください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
using System.Collections; using System.Collections.Generic; using UnityEngine; public class DestroyObject : MonoBehaviour { public int damage; //当たった部位毎のダメージ量 private GameObject enemy; //敵オブジェクト private HP hp; //HPクラス void Start() { enemy = GameObject.Find("Enemy"); //敵情報を取得 hp = enemy.GetComponent<HP>(); //HP情報を取得 } void OnTriggerEnter(Collider other){ //ぶつかったオブジェクトのTagにShellという名前が書いてあったならば(条件). if (other.CompareTag("Shell")){ //HPクラスのDamage関数を呼び出す hp.Damage(damage); //ぶつかってきたオブジェクトを破壊する. Destroy(other.gameObject); } } } |
このスクリプトは「Enemy」に「Shell」が当たった際のダメージ量を、任意で設定できるようにしたものです。そのためには「Enemy」オブジェクトに「Shell」オブジェクトを「Shell」と認識させる必要があります。
上記スクリプトにも書いてあるように「Shell」にTag付けをします。AssetsエリアのPrefabフォルダを開き「Shell」を選択してください。
Inspectorエリアの“Untagged”をクリックし“Add Tag…”を選択してください。
次に“+“をクリックしTagの名前を”Shell“にしてSaveします。
Saveが完了したらもう一度Prefabフォルダの「Shell」を開きInspectorエリアの“Untagged”をクリックします。
すると先ほど追加した“Shell”のTagが選択できるようになっているはずです。
上記の画像の手順で“Shell”のTagを選択してTag付け完了です。
続いて先ほど作成した「DestroyObject」スクリプトを「Enemy」の子オブジェクトに割り振ってください。
上記の画像のように「Head」以外の子オブジェクトにも割り振ってください。
それぞれ任意で各部位のダメージ量を設定してください。上記の画像は「Head」にあたった際のダメージ量です。
以上で設定は終了です。試し打ちをしてみましょう。
試し打ち
* 「Enemy」: HP.100 に対して
「Head」: 100
「Body」: 25
「Right_Arm」「Left_Arm」「Right_Leg」「Left_Leg」: 20
のダメージ量で設定しています。
「Body」にあたった場合(25ダメージ)
「Right_Arm」(手足)にあたった場合(20ダメージ)
「Head」にあたった(100ダメージ・即死)の場合
それぞれ設定したダメージが「Enemy」のHPに反映されていることが確認できれば成功です。
ダメージ量を調整することで、FPSゲームでよく見るヘッドショット機能も実現することができます。
まとめ
いかがだったでしょうか。
今回はFPSにおけるあたり判定の使い分けについて触れてきました。今回作成したスクリプトは合計4つですが、使い方次第でFPSの基本的な構造を作り出すことができます。
少しでも興味を持っていただけたら幸いです。
この記事はいかがでしたか?
もし「参考になった」「面白かった」という場合は、応援シェアお願いします!