MiniGames/Assets/Scripts/CrateEscape/CrateEscapeCameraFollow.cs

102 lines
3.3 KiB
C#

using UnityEngine;
using DG.Tweening;
public class CrateEscapeCameraFollow : MonoBehaviour
{
[Header("Targets")]
public Transform player; // follow target
public Transform topDownAnchor; // start view (pos+rot)
public Transform gameplayAnchor; // after-intro view (pos+rot)
[Header("Timing")]
public float introHoldSeconds = 3f; // top-down hold
public float transitionSeconds = 1f; // tween duration to gameplay view
public bool useUnscaledTime = false; // set true if you pause timeScale during intro
[Header("Follow")]
public float followSmoothTime = 0.20f; // SmoothDamp time
public float maxFollowSpeed = Mathf.Infinity;
// runtime
private Vector3 _worldOffset;
private Quaternion _lockedRotation;
private Vector3 _vel;
private bool _following;
private Sequence _seq;
void Start()
{
if (!player || !gameplayAnchor)
{
Debug.LogError("[CameraFollow] Assign player & gameplayAnchor.");
enabled = false;
return;
}
// snap to top-down if provided, otherwise keep current
if (topDownAnchor)
{
transform.position = topDownAnchor.position;
transform.rotation = topDownAnchor.rotation;
}
StartCoroutine(BeginFlow());
}
System.Collections.IEnumerator BeginFlow()
{
// 1) Hold top-down
if (introHoldSeconds > 0f)
{
if (useUnscaledTime) yield return new WaitForSecondsRealtime(introHoldSeconds);
else yield return new WaitForSeconds(introHoldSeconds);
}
// 2) Tween to your provided gameplay pose
_seq?.Kill();
_seq = DOTween.Sequence().SetUpdate(useUnscaledTime)
.Join(transform.DOMove(gameplayAnchor.position, transitionSeconds).SetEase(Ease.InOutSine))
.Join(transform.DORotateQuaternion(gameplayAnchor.rotation, transitionSeconds).SetEase(Ease.InOutSine))
.OnComplete(() =>
{
// 3) Lock rotation & compute world offset for follow
_lockedRotation = gameplayAnchor.rotation;
_worldOffset = gameplayAnchor.position - player.position;
_following = true;
});
yield break;
}
void LateUpdate()
{
if (!_following || !player) return;
// keep rotation fixed (no camera roll/yaw changes during follow)
if (transform.rotation != _lockedRotation)
transform.rotation = _lockedRotation;
Vector3 targetPos = player.position + _worldOffset;
if (useUnscaledTime)
{
transform.position = Vector3.SmoothDamp(
transform.position, targetPos, ref _vel, followSmoothTime, maxFollowSpeed, Time.unscaledDeltaTime);
}
else
{
transform.position = Vector3.SmoothDamp(
transform.position, targetPos, ref _vel, followSmoothTime, maxFollowSpeed);
}
}
void OnDisable() => _seq?.Kill();
/// Call if the player respawns or you reposition the gameplayAnchor at runtime.
public void RecenterToGameplayAnchor()
{
_lockedRotation = gameplayAnchor.rotation;
_worldOffset = gameplayAnchor.position - player.position;
}
}