「Unity/3d/FPS」の版間の差分
提供: 初心者エンジニアの簡易メモ
(ページの作成:「==FPS視点カメラ== #ヒエラルキーからCreateEmptyして新規オブジェクトを作成しオブジェクト名を"Player"とする #MainCameraのオブジェ...」) |
(→プレイヤーの移動) |
||
(同じ利用者による、間の1版が非表示) | |||
行71: | 行71: | ||
参考:https://xr-hub.com/archives/7782 | 参考:https://xr-hub.com/archives/7782 | ||
+ | |||
+ | ==透明な弾を打つ== | ||
+ | |||
+ | #AssetsStoreで"War FX"を検索 | ||
+ | #以下csをGunに貼り付ける | ||
+ | <pre> | ||
+ | using System.Collections; | ||
+ | using System.Collections.Generic; | ||
+ | using UnityEngine; | ||
+ | public class RayGunController : MonoBehaviour | ||
+ | { | ||
+ | public enum ShootMode { AUTO, SEMIAUTO } | ||
+ | public bool shootEnabled = true; | ||
+ | [SerializeField] | ||
+ | ShootMode shootMode = ShootMode.AUTO; | ||
+ | [SerializeField] | ||
+ | int maxAmmo = 1000; | ||
+ | [SerializeField] | ||
+ | int damage = 1; | ||
+ | [SerializeField] | ||
+ | float shootInterval = 0.15f; | ||
+ | [SerializeField] | ||
+ | float shootRange = 50; | ||
+ | [SerializeField] | ||
+ | Vector3 muzzleFlashScale; | ||
+ | [SerializeField] | ||
+ | GameObject muzzleFlashPrefab; | ||
+ | [SerializeField] | ||
+ | GameObject hitEffectPrefab; | ||
+ | bool shooting = false; | ||
+ | int ammo; | ||
+ | GameObject muzzleFlash; | ||
+ | GameObject hitEffect; | ||
+ | public int Ammo | ||
+ | { | ||
+ | set | ||
+ | { | ||
+ | ammo = Mathf.Clamp(value, 0, maxAmmo); | ||
+ | } | ||
+ | get | ||
+ | { | ||
+ | return ammo; | ||
+ | } | ||
+ | } | ||
+ | void Start() | ||
+ | { | ||
+ | InitGun(); | ||
+ | } | ||
+ | void Update() | ||
+ | { | ||
+ | if (shootEnabled & ammo > 0 & GetInput()) | ||
+ | { | ||
+ | StartCoroutine(ShootTimer()); | ||
+ | } | ||
+ | } | ||
+ | void InitGun() | ||
+ | { | ||
+ | Ammo = maxAmmo; | ||
+ | } | ||
+ | bool GetInput() | ||
+ | { | ||
+ | switch (shootMode) | ||
+ | { | ||
+ | case ShootMode.AUTO: | ||
+ | return Input.GetMouseButton(0); | ||
+ | case ShootMode.SEMIAUTO: | ||
+ | return Input.GetMouseButtonDown(0); | ||
+ | } | ||
+ | return false; | ||
+ | } | ||
+ | IEnumerator ShootTimer() | ||
+ | { | ||
+ | if (!shooting) | ||
+ | { | ||
+ | shooting = true; | ||
+ | if (muzzleFlashPrefab != null) | ||
+ | { | ||
+ | if (muzzleFlash != null) | ||
+ | { | ||
+ | muzzleFlash.SetActive(true); | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | muzzleFlash = Instantiate(muzzleFlashPrefab, transform.position, transform.rotation); | ||
+ | muzzleFlash.transform.SetParent(gameObject.transform); | ||
+ | muzzleFlash.transform.localScale = muzzleFlashScale; | ||
+ | } | ||
+ | } | ||
+ | Shoot(); | ||
+ | yield return new WaitForSeconds(shootInterval); | ||
+ | if (muzzleFlash != null) | ||
+ | { | ||
+ | muzzleFlash.SetActive(false); | ||
+ | } | ||
+ | if (hitEffect != null) | ||
+ | { | ||
+ | if (hitEffect.activeSelf) | ||
+ | { | ||
+ | hitEffect.SetActive(false); | ||
+ | } | ||
+ | } | ||
+ | shooting = false; | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | yield return null; | ||
+ | } | ||
+ | } | ||
+ | void Shoot() | ||
+ | { | ||
+ | Ray ray = new Ray(transform.position, transform.forward); | ||
+ | RaycastHit hit; | ||
+ | if (Physics.Raycast(ray, out hit, shootRange)) | ||
+ | { | ||
+ | if (hitEffectPrefab != null) | ||
+ | { | ||
+ | if (hitEffect != null) | ||
+ | { | ||
+ | hitEffect.transform.position = hit.point; | ||
+ | hitEffect.transform.rotation = Quaternion.FromToRotation(Vector3.forward, hit.normal); | ||
+ | hitEffect.SetActive(true); | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | hitEffect = Instantiate(hitEffectPrefab, hit.point, Quaternion.identity); | ||
+ | } | ||
+ | } | ||
+ | Debug.Log("hit=" + hit.collider.gameObject.name); // こんな感じで敵のオブジェクト名取得 | ||
+ | } | ||
+ | Ammo--; | ||
+ | } | ||
+ | } | ||
+ | </pre> | ||
+ | |||
+ | 参考:https://unity.moon-bear.com/zombie-slayer/shoot-and-effect/ | ||
+ | |||
+ | ==プレイヤーの移動== | ||
+ | #RigidbodyをPlayerに追加 | ||
+ | #下に落ちてしまう場合は、床をPlaneで作り、床にAddComponentでBoxColliderを追加し、PlayerにもCapsuleColliderを追加する | ||
+ | #以下のようなPlayerController.csを作る | ||
+ | |||
+ | <pre>using System.Collections; | ||
+ | using System.Collections.Generic; | ||
+ | using UnityEngine; | ||
+ | |||
+ | public class PlayerController : MonoBehaviour | ||
+ | { | ||
+ | Rigidbody m_Rigidbody; | ||
+ | |||
+ | void Start() | ||
+ | { | ||
+ | // 自分のRigidbodyを取ってくる | ||
+ | m_Rigidbody = GetComponent<Rigidbody>(); | ||
+ | } | ||
+ | |||
+ | void Update() | ||
+ | { | ||
+ | // 十字キーで首を左右に回す | ||
+ | if (Input.GetKey(KeyCode.RightArrow)) | ||
+ | { | ||
+ | transform.Rotate(new Vector3(0.0f, 1.0f, 0.0f)); | ||
+ | } | ||
+ | if (Input.GetKey(KeyCode.LeftArrow)) | ||
+ | { | ||
+ | transform.Rotate(new Vector3(0.0f, -1.0f, 0.0f)); | ||
+ | } | ||
+ | |||
+ | // WASDで移動する | ||
+ | float x = 0.0f; | ||
+ | float z = 0.0f; | ||
+ | |||
+ | if (Input.GetKey(KeyCode.D)) | ||
+ | { | ||
+ | x += 1.0f; | ||
+ | } | ||
+ | if (Input.GetKey(KeyCode.A)) | ||
+ | { | ||
+ | x -= 1.0f; | ||
+ | } | ||
+ | if (Input.GetKey(KeyCode.W)) | ||
+ | { | ||
+ | z += 1.0f; | ||
+ | } | ||
+ | if (Input.GetKey(KeyCode.S)) | ||
+ | { | ||
+ | z -= 1.0f; | ||
+ | } | ||
+ | m_Rigidbody.velocity = new Vector3(x, 0.0f, z); | ||
+ | } | ||
+ | } | ||
+ | </pre> | ||
+ | 参考:http://chungames.hateblo.jp/entry/2016/07/31/201807 |
2020年6月10日 (水) 14:27時点における最新版
FPS視点カメラ
- ヒエラルキーからCreateEmptyして新規オブジェクトを作成しオブジェクト名を"Player"とする
- MainCameraのオブジェクト名を"FSPCamera"へ変更
- Playerの下にFSPCameraを移動
- 以下csを作成してFPSCameraへドラッグ
FPSCamera.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; namespace FPS { public class FPSCamera : MonoBehaviour { private Transform _camTransform; //マウス操作の始点 private Vector3 _startMousePos; //カメラ回転の始点情報 private Vector3 _presentCamRotation; void Start() { _camTransform = this.gameObject.transform; } void Update() { //カメラの回転 マウス CameraRotationMouseControl(); } //カメラの回転 マウス private void CameraRotationMouseControl() { if (Input.GetMouseButtonDown(0)) { _startMousePos = Input.mousePosition; _presentCamRotation.x = _camTransform.transform.eulerAngles.x; _presentCamRotation.y = _camTransform.transform.eulerAngles.y; } if (Input.GetMouseButton(0)) { //(移動開始座標 - マウスの現在座標) / 解像度 で正規化 float x = (_startMousePos.x - Input.mousePosition.x) / Screen.width; float y = (_startMousePos.y - Input.mousePosition.y) / Screen.height; //回転開始角度 + マウスの変化量 * 90 float eulerX = _presentCamRotation.x + y * 90.0f; float eulerY = _presentCamRotation.y + x * 90.0f; _camTransform.rotation = Quaternion.Euler(eulerX, eulerY, 0); } } } }
参考:https://qiita.com/Nekomasu/items/0a6aaf1f595cf05fbd0d
参考:https://xr-hub.com/archives/7782
銃オブジェクト追加
- AssetStoreで銃(例:"FPS-AKM"で出てくる)を追加
- 銃をヒエラルキーに追加し、オブジェクト名を"Gun"に変更する
- FPSCameraの子にGunを移動
参考:https://xr-hub.com/archives/7782
透明な弾を打つ
- AssetsStoreで"War FX"を検索
- 以下csをGunに貼り付ける
using System.Collections; using System.Collections.Generic; using UnityEngine; public class RayGunController : MonoBehaviour { public enum ShootMode { AUTO, SEMIAUTO } public bool shootEnabled = true; [SerializeField] ShootMode shootMode = ShootMode.AUTO; [SerializeField] int maxAmmo = 1000; [SerializeField] int damage = 1; [SerializeField] float shootInterval = 0.15f; [SerializeField] float shootRange = 50; [SerializeField] Vector3 muzzleFlashScale; [SerializeField] GameObject muzzleFlashPrefab; [SerializeField] GameObject hitEffectPrefab; bool shooting = false; int ammo; GameObject muzzleFlash; GameObject hitEffect; public int Ammo { set { ammo = Mathf.Clamp(value, 0, maxAmmo); } get { return ammo; } } void Start() { InitGun(); } void Update() { if (shootEnabled & ammo > 0 & GetInput()) { StartCoroutine(ShootTimer()); } } void InitGun() { Ammo = maxAmmo; } bool GetInput() { switch (shootMode) { case ShootMode.AUTO: return Input.GetMouseButton(0); case ShootMode.SEMIAUTO: return Input.GetMouseButtonDown(0); } return false; } IEnumerator ShootTimer() { if (!shooting) { shooting = true; if (muzzleFlashPrefab != null) { if (muzzleFlash != null) { muzzleFlash.SetActive(true); } else { muzzleFlash = Instantiate(muzzleFlashPrefab, transform.position, transform.rotation); muzzleFlash.transform.SetParent(gameObject.transform); muzzleFlash.transform.localScale = muzzleFlashScale; } } Shoot(); yield return new WaitForSeconds(shootInterval); if (muzzleFlash != null) { muzzleFlash.SetActive(false); } if (hitEffect != null) { if (hitEffect.activeSelf) { hitEffect.SetActive(false); } } shooting = false; } else { yield return null; } } void Shoot() { Ray ray = new Ray(transform.position, transform.forward); RaycastHit hit; if (Physics.Raycast(ray, out hit, shootRange)) { if (hitEffectPrefab != null) { if (hitEffect != null) { hitEffect.transform.position = hit.point; hitEffect.transform.rotation = Quaternion.FromToRotation(Vector3.forward, hit.normal); hitEffect.SetActive(true); } else { hitEffect = Instantiate(hitEffectPrefab, hit.point, Quaternion.identity); } } Debug.Log("hit=" + hit.collider.gameObject.name); // こんな感じで敵のオブジェクト名取得 } Ammo--; } }
参考:https://unity.moon-bear.com/zombie-slayer/shoot-and-effect/
プレイヤーの移動
- RigidbodyをPlayerに追加
- 下に落ちてしまう場合は、床をPlaneで作り、床にAddComponentでBoxColliderを追加し、PlayerにもCapsuleColliderを追加する
- 以下のようなPlayerController.csを作る
using System.Collections; using System.Collections.Generic; using UnityEngine; public class PlayerController : MonoBehaviour { Rigidbody m_Rigidbody; void Start() { // 自分のRigidbodyを取ってくる m_Rigidbody = GetComponent<Rigidbody>(); } void Update() { // 十字キーで首を左右に回す if (Input.GetKey(KeyCode.RightArrow)) { transform.Rotate(new Vector3(0.0f, 1.0f, 0.0f)); } if (Input.GetKey(KeyCode.LeftArrow)) { transform.Rotate(new Vector3(0.0f, -1.0f, 0.0f)); } // WASDで移動する float x = 0.0f; float z = 0.0f; if (Input.GetKey(KeyCode.D)) { x += 1.0f; } if (Input.GetKey(KeyCode.A)) { x -= 1.0f; } if (Input.GetKey(KeyCode.W)) { z += 1.0f; } if (Input.GetKey(KeyCode.S)) { z -= 1.0f; } m_Rigidbody.velocity = new Vector3(x, 0.0f, z); } }