はじめに
BodyをFraming TransposerでAimをPOVに設定した3人称カメラにリセット機能を実装を実装していきます
3人称カメラの作成は下記記事を参考にしました https://raspberly.hateblo.jp/entry/UnityAdventCalendar2022_24#fn-d34631a8
環境は Unity 2021.3.25f1です
Universal Render Pipeline を使用しています。
スクリプト作成
Cinemachineやカメラのパラメータは設定してある前提です
一瞬で視点をリセットさせる
CinemachinePOVのHorizontalAxis.ValueにとキャラのeulerAngles.yを一緒にすることで視点をリセットできます
using System.Collections; using System.Collections.Generic; using UnityEngine; using Cinemachine; public class TestCamera : MonoBehaviour { [SerializeField] CinemachineVirtualCamera mVirtualCamera; CinemachinePOV mPov; [SerializeField] Transform characotr; private void Start() { if (mPov == null) { mPov = mVirtualCamera.GetCinemachineComponent<CinemachinePOV>(); } } private void Update() { if(Input.GetKeyDown(KeyCode.R)) { ResetRot(); } } /// <summary> /// 視点のリセット /// </summary> public void ResetRot() { mPov.m_HorizontalAxis.Value = characotr.transform.eulerAngles.y; mPov.m_VerticalAxis.Value = 0; } }
徐々に視点をリセットさせる
基本的には角度をLerpで変化させてるだけですが角度-180~180の範囲なのでそこだけ注意する必要があります
using System.Collections; using System.Collections.Generic; using UnityEngine; using Cinemachine; public class TestCamera : MonoBehaviour { [SerializeField] CinemachineVirtualCamera mVirtualCamera; CinemachinePOV mPov; [SerializeField] Transform characotr; //カメラリセットパラメーター bool ImsRest = false;//カメラの向きをリセットするか [SerializeField, Range(0, 2)] float mResetTime = 0.3f;//リセット終えるまでにかかる時間 private float mCurrentCameraHorizontalAngles = 0; private float mCurrentCharactorHorizontalAngles = 0; private float mCurrentTime = 0; private void Start() { if (mPov == null) { mPov = mVirtualCamera.GetCinemachineComponent<CinemachinePOV>(); } } private void Update() { if (Input.GetKeyDown(KeyCode.R)) { //ResetRot(); StartReset(); } if (ImsRest) { ResetUpdate(); } } public void StartReset() { var dire = Vector3.SignedAngle(transform.forward, characotr.transform.forward, Vector3.up); //正面に向いていたら if (dire == 0) { return; } ImsRest = true; mCurrentTime = 0; //現在の角度を保存 mCurrentCameraHorizontalAngles = mPov.m_HorizontalAxis.Value; mCurrentCharactorHorizontalAngles = Mathf.Repeat(characotr.transform.eulerAngles.y + 180, 360) - 180;//-180~180に変換 } /// <summary> /// リセット更新 /// </summary> void ResetUpdate() { var targetY = mCurrentCharactorHorizontalAngles; var targetX = 0; mCurrentTime += Time.deltaTime; //リセット完了 if (mCurrentTime >= mResetTime) { mCurrentTime = 0; ImsRest = false; mPov.m_HorizontalAxis.Value = targetY; mPov.m_VerticalAxis.Value = targetX; return; } var nextHorizontal = 0f; //本来は右回転(Playerは右向き)だがカメラが左回転になってしまう場合 if (mCurrentCameraHorizontalAngles - targetY >= 180) { targetY += 360; nextHorizontal = Mathf.Lerp(mCurrentCameraHorizontalAngles, targetY, mCurrentTime / mResetTime) - 360; mPov.m_HorizontalAxis.Value = nextHorizontal; }//本来は左回転(Playerは右向き)だがカメラが右回転になってしまう場合 else if (mCurrentCameraHorizontalAngles - targetY <= -180) { targetY -= 360; nextHorizontal = Mathf.Lerp(mCurrentCameraHorizontalAngles, targetY, mCurrentTime / mResetTime) + 360; mPov.m_HorizontalAxis.Value = nextHorizontal; }//通常回転 else { mPov.m_HorizontalAxis.Value = Mathf.Lerp(mCurrentCameraHorizontalAngles, targetY, mCurrentTime / mResetTime); } //縦軸の回転 mPov.m_VerticalAxis.Value = Mathf.Lerp(mPov.m_VerticalAxis.Value, targetX, mCurrentTime / mResetTime); } /// <summary> /// 視点のリセット /// </summary> public void ResetRot() { mPov.m_HorizontalAxis.Value = characotr.transform.eulerAngles.y; mPov.m_VerticalAxis.Value = 0; } }