MiniGames/Assets/Scripts/Shared/SmoothChildRotation.cs
2025-09-09 16:46:17 +05:00

135 lines
4.7 KiB
C#
Raw Blame History

using UnityEngine;
using DG.Tweening;
[RequireComponent(typeof(Collider))]
public class SmoothChildRotation : MonoBehaviour
{
[Header("Door Parts")]
public Transform targetChild; // door mesh child to rotate
public string playerTag = "Player";
[Header("Door Rotation")]
public float rotationDuration = 0.5f;
public Ease rotationEase = Ease.OutQuad;
public Vector3 targetRotationOnEnter = new Vector3(0, 0, -90);
public Vector3 targetRotationOnExit = new Vector3(0, 0, 0);
[Header("Cutscene: Exit Path")]
[Tooltip("If not set, we use (this.transform.position + this.transform.forward * exitForwardDistance).")]
public Transform exitPoint;
public float exitForwardDistance = 3f; // used when exitPoint is null
public float faceDuration = 0.2f; // how quickly the player faces exit
[Header("Cutscene: Anim States")]
public string celebrationStateName = "Celebration";
public string walkStateName = "Run"; // or your locomotion state/BT name
[Header("Cutscene: Timing")]
public float celebrationDuration = 1.2f; // seconds to hold Celebration
public float walkMoveDuration = 1.5f; // seconds to walk to exit
public Ease walkMoveEase = Ease.Linear;
[Header("Behavior")]
public bool disableTriggerAfterUse = true; // prevents re-entrant triggers
private Tween _doorTween;
private bool _cutsceneRunning;
void Reset()
{
var col = GetComponent<Collider>();
if (col) col.isTrigger = true;
}
void Start()
{
if (!targetChild)
{
Debug.LogError("[SmoothChildRotation] Target child not assigned!", this);
enabled = false;
}
}
void OnTriggerEnter(Collider other)
{
if (_cutsceneRunning) return;
if (!other.CompareTag(playerTag)) return;
// Open the door
RotateTo(targetRotationOnEnter);
// Start the cutscene
StartCoroutine(RunDoorCutscene(other));
}
void OnTriggerExit(Collider other)
{
if (!other.CompareTag(playerTag)) return;
if (_cutsceneRunning) return; // don<6F>t close while cutscene is ongoing
RotateTo(targetRotationOnExit);
}
void RotateTo(Vector3 targetRot)
{
_doorTween?.Kill();
_doorTween = targetChild
.DOLocalRotate(targetRot, rotationDuration)
.SetEase(rotationEase);
}
System.Collections.IEnumerator RunDoorCutscene(Collider hit)
{
_cutsceneRunning = true;
if (disableTriggerAfterUse) { var c = GetComponent<Collider>(); if (c) c.enabled = false; }
// Find player components
Transform root = hit.attachedRigidbody ? hit.attachedRigidbody.transform : hit.transform.root;
var controller = root.GetComponentInChildren<CrateEscapePlayerControllerJoystick>();
var anim = root.GetComponentInChildren<ZibuAnimDriver>();
var rb = root.GetComponentInChildren<Rigidbody>();
// 1) Freeze player control & velocity
if (controller) controller.LockControls(true);
if (rb) { rb.velocity = Vector3.zero; rb.angularVelocity = Vector3.zero; }
// 2) Work out exit position / facing
Vector3 dst = exitPoint ? exitPoint.position : (transform.position + transform.forward * exitForwardDistance);
if (rb) dst.y = rb.position.y; else dst.y = root.position.y;
Vector3 faceDir = dst - root.position; faceDir.y = 0f;
if (faceDir.sqrMagnitude > 0.0001f)
{
Quaternion look = Quaternion.LookRotation(faceDir.normalized, Vector3.up);
// quick face toward the door exit
root.DORotateQuaternion(look, faceDuration).SetEase(Ease.OutQuad);
}
// 3) Celebration anim
if (anim && !string.IsNullOrEmpty(celebrationStateName))
anim.PlayState(celebrationStateName, 0.1f);
yield return new WaitForSeconds(celebrationDuration);
// 4) Walk/Run anim
if (anim && !string.IsNullOrEmpty(walkStateName))
anim.PlayState(walkStateName, 0.1f);
// 5) Move player outside the door
Tween moveT;
if (rb != null)
moveT = rb.DOMove(dst, walkMoveDuration).SetEase(walkMoveEase).SetUpdate(UpdateType.Fixed);
else
moveT = root.DOMove(dst, walkMoveDuration).SetEase(walkMoveEase);
yield return moveT.WaitForCompletion();
// 6) Level complete signal
CrateEscapeGameManager.Instance?.OnLevelCompleteTriggered();
// (Optional) keep controls locked while level completes. Remove next line if you want to give control back:
// if (controller) controller.LockControls(false);
_cutsceneRunning = false;
}
}