Menu
CoddyTech

カメラシェイク

CoddyのUnityジャーニー「物理演算とゲームプレイ」セクションの一部。レッスン 48/63。

シェイクとは、ランダムなオフセットを短時間適用することです。数分の1秒の間、カメラは元の位置の近くにあるランダムな場所にとどまり、フレームごとに新しい位置へ移動してから、元の位置に戻ります。コルーチンは複数のフレームにわたって実行され、自動的に終了するため、これに適しています。このカメラは、岩が着地したときにシェイクします(別のスクリプトが BoulderLanded() を呼び出します。IEnumerator を使うため、ファイルの先頭には using System.Collections; があります)。

public float strength = 0.2f;
public float duration = 0.4f;
Vector3 rest;

void Start()
{
    rest = transform.localPosition;
}

public void BoulderLanded()
{
    StartCoroutine(Shake());
}

IEnumerator Shake()
{
    float elapsed = 0f;
    while (elapsed < duration)
    {
        transform.localPosition = rest + Random.insideUnitSphere * strength;
        elapsed += Time.deltaTime;
        yield return null;
    }
    transform.localPosition = rest;
}

Random.insideUnitSphere * strength は、任意の方向に最大 strength の長さでランダムにオフセットします。また、yield return null によって、次のフレームで新しいオフセットが選ばれます。各ループで Time.deltaTime を加算することで実際の秒数を数えるため、フレームレートに関係なく、シェイクは duration の間続きます。最後の行でカメラを元の位置に戻します。これがないと、最後のオフセットが残した位置にカメラがとどまります。

各フレームでUnityは、すべての Update() を実行し、次に yield return null で待機しているコルーチンを実行し、その後すべての LateUpdate() を実行します。そのため、LateUpdate() で位置を設定する追従カメラは、シェイクによる変更を上書きします。カメラが追従を行う空のオブジェクトの子であれば、localPosition をシェイクすることでこれを回避できます。親オブジェクトが移動し、カメラはその下での位置を中心にシェイクします。

challenge icon

チャレンジ

中級

このカメラはプレイヤーを追従します(矢印キーでプレイヤーを動かします)。LateUpdate()では、プレイヤーの位置にoffsetを加えた位置にあり、何の子オブジェクトにもなっていません。追従しながら揺れるようにしましょう。

  • Spaceキーを押すと、duration(0.4)秒間揺れます。揺れている間、カメラはプレイヤーを追い続けながら、追従位置から最大strength(0.3)だけ離れた新しいランダムな位置に、毎フレーム移動します。
  • 揺れが終わると、追従位置にぴったり戻ります。

Spaceキーを押すと、すでにShake()コルーチンが開始されます。Playを押して、動かしてSpaceキーを押し、それからCheckを押してください。

自分で試してみよう

using System.Collections;
using UnityEngine;

public class ShakeFollow : MonoBehaviour
{
    public Transform player;
    public Vector3 offset = new Vector3(0, 4, -8);
    public float strength = 0.3f;
    public float duration = 0.4f;

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            StartCoroutine(Shake());
        }
    }

    void LateUpdate()
    {
        transform.position = player.position + offset;
    }

    IEnumerator Shake()
    {
        // カメラを追従位置から最大strengthの幅でduration秒間揺らす。
        yield return null;
    }
}
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

物理演算とゲームプレイのすべてのレッスン