Unity - 画面を揺らす
初めに
ゲームでは、画面を揺らすことで衝撃やダメージを演出する場合があります。本記事では、カメラを直接揺らして、画面の揺れを表現する方法を説明します。
Index
固定カメラの場合
固定カメラの場合、カメラの初期位置を取得しておいて、そこを中心にカメラの位置を移動させればよいでしょう。
次のスクリプトをカメラにつけ、Shake 関数を呼び出すことで、画面の揺れを実装できます。
using UnityEngine; public class ScreenShake : MonoBehaviour { public float shakeDuration = 0.3f; // 揺れの継続時間 public float shakeMagnitude = 0.1f; // 揺れの大きさ public float dampingSpeed = 1.0f; // 揺れの減衰速度 private Vector3 initialPosition; // カメラの初期位置 private float shakeTimer = 0.0f; // 揺れのタイマー void Awake() { // カメラの初期位置を保存 initialPosition = transform.localPosition; } void Update() { if (shakeTimer > 0) { // 揺れの大きさをランダムに生成 Vector3 shakeOffset = Random.insideUnitSphere * shakeMagnitude; // カメラの位置に揺れを加える transform.localPosition = initialPosition + shakeOffset; // 揺れのタイマーを減少させる shakeTimer -= Time.deltaTime * dampingSpeed; } else { // 揺れが終了したらカメラの位置を初期位置に戻す transform.localPosition = initialPosition; } } public void Shake() { // 揺れのタイマーを設定 shakeTimer = shakeDuration; } }
変数 | 説明 |
---|---|
shakeDuration | 揺れの継続時間 |
shakeMagnitude | 揺れの大きさ |
dampingSpeed | 揺れの減衰速度 |
(実行)
youtu.be
カメラが移動する場合
カメラが移動する場合は、カメラの初期位置を保存するわけにはいかないので、別の方法を考えます。本記事では、カメラが移動した分、毎回逆方向に戻すことで、カメラを適切な位置に戻しています。
using UnityEngine; public class ScreenShake : MonoBehaviour { public float shakeDuration = 0.3f; // 揺れの継続時間 public float shakeMagnitude = 0.1f; // 揺れの大きさ public float dampingSpeed = 1.0f; // 揺れの減衰速度 private Vector3 initialPosition; // カメラの初期位置 private float shakeTimer = 0.0f; // 揺れのタイマー private Vector3 currentShakeOffset = Vector3.zero; void Awake() { // カメラの初期位置を保存 initialPosition = transform.localPosition; } void Update() { if (Input.GetKey(KeyCode.Space)) Shake(); if (shakeTimer > 0) { // 揺れの大きさをランダムに生成 Vector3 shakeOffset = currentShakeOffset == Vector3.zero ? Random.insideUnitSphere * shakeMagnitude : GetOppositeVector(currentShakeOffset) * shakeMagnitude; // 累積したオフセットを差し引く transform.localPosition -= currentShakeOffset; // カメラの位置に揺れを加える transform.localPosition += shakeOffset; // 揺れのタイマーを減少させる shakeTimer -= Time.deltaTime * dampingSpeed; // shakeOffsetで動いた量を保存する currentShakeOffset = shakeOffset; } else { if (currentShakeOffset != Vector3.zero) { transform.localPosition -= currentShakeOffset; currentShakeOffset = Vector3.zero; } } } public void Shake() { // カメラの初期位置を保存 initialPosition = transform.localPosition; // 揺れのタイマーを設定 shakeTimer = shakeDuration; } // ベクトルの符号を判定し、逆の符号の成分を持つランダムなベクトルを取得するメソッド Vector3 GetOppositeVector(Vector3 vector) { Vector3 oppositeVector = Vector3.zero; // 各成分の符号を判定し、逆の符号の成分を持つランダムなベクトルを生成 if (vector.x > 0) oppositeVector.x = Random.Range(-1.0f, 0.0f); else if (vector.x < 0) oppositeVector.x = Random.Range(0.0f, 1.0f); if (vector.y > 0) oppositeVector.y = Random.Range(-1.0f, 0.0f); else if (vector.y < 0) oppositeVector.y = Random.Range(0.0f, 1.0f); if (vector.z > 0) oppositeVector.z = Random.Range(-1.0f, 0.0f); else if (vector.z < 0) oppositeVector.z = Random.Range(0.0f, 1.0f); return oppositeVector.normalized; } }
(実行)
youtu.be