プレイヤーに追従するカメラ(カクつかない方法、滑らかに追従する方法)

3Dゲームでの一人称視点(FPS的な)、三人称視点(TPS的な)で使う、プレイヤーを追従するカメラの作り方です。

まあ普通にカメラのpositionをプレイヤーのpositionと紐づければいいだけなんですけど、プレイヤーを動かすと画面がかくついてしまう!という方、さらにはプレイヤーの動きに少し遅れてついていくカメラを作りたい!という方は是非ご覧ください。

カクつくときのよくあるミス

プレイヤーの移動をUpdate()内に記述しているとき、カメラの移動も別のスクリプトのUpdate()内に記述していませんか??

同じスクリプトの中のUpdate()内なら別に問題ないのですが、別のスクリプトに書いてしまうと問題が起きてしまいます。

別のスクリプトのUpdate()はどの順番で呼ばれるかがランダムなため、「プレイヤーの移動→カメラの移動」の瞬間もあれば「カメラの移動→プレイヤーの移動」の瞬間もあるわけで、これが原因でカメラの動き(画面の動き)がカクついてしまうのです。

ということで、プレイヤーの移動をUpdate()内に書いた場合、カメラの移動はLateUpdate()内に書きましょう!


public class CameraControl : MonoBehaviour {

	Transform cameraTrans;
	[SerializeField] Transform playerTrans;

	[SerializeField] Vector3 cameraVec;  //Vector3(0, 1, -1)
	[SerializeField] Vector3 cameraRot;  //Vector3(45, 0, 0)

	void Awake(){
		cameraTrans = transform;
		cameraTrans.rotation = Quaternion.Euler(cameraRot);
	}

	void LateUpdate(){
		cameraTrans.position = playerTrans.position + cameraVec;
	}
}

LateUpdate()は全てのスクリプトのUpdate()が処理された後に必ず実行されるため、毎フレーム「プレイヤーの移動→カメラの移動」という順番で一定して処理することができます。

これでカクつくのを防ぐことができました!

少し遅れて追従するカメラ

プレイヤーの動きにぴったりついてくるカメラではなく、時間差で少し遅れてプレイヤーの動きについてくるようなカメラにしたい場合。


void LateUpdate(){
//	cameraTrans.position = playerTrans.position + cameraVec;
	cameraTrans.position = Vector3.Lerp(cameraTrans.position, playerTrans.position + cameraVec, 2.0f * Time.deltaTime);
}

このように書き換えると少し遅れて滑らかな感じで追従するカメラになります。

コメント