using System.Collections; using UnityEngine; public class RoomExitGate : MonoBehaviour { [Header("Gate Root")] [SerializeField] private GameObject gateVisualRoot; [Header("Door")] [SerializeField] private Transform leftDoor; [SerializeField] private Transform rightDoor; [Header("Door Open Angle")] [SerializeField] private float leftOpenAngleY = 110f; [SerializeField] private float rightOpenAngleY = -110f; [Header("Portal")] [SerializeField] private GameObject portalEffectRoot; [SerializeField] private ParticleSystem[] portalParticles; [Header("Open Effect")] [SerializeField] private ParticleSystem openParticle; [SerializeField] private AudioSource openSound; [Header("Trigger")] [SerializeField] private Collider gateTrigger; [Header("Timing")] [SerializeField] private float openDelay = 1.2f; [SerializeField] private float openDuration = 1.2f; [SerializeField] private float portalShowDelay = 0.3f; [Header("Player Check")] [SerializeField] private string playerTag = "Player"; [Header("Scene Move")] [SerializeField] private bool useRandomScene = true; [SerializeField] private string fallbackSceneName; [SerializeField] private float sceneMoveDelay = 0.2f; [Header("Start Setting")] [SerializeField] private bool hideGateOnStart = true; [SerializeField] private bool hidePortalOnStart = true; private Quaternion leftClosedRotation; private Quaternion rightClosedRotation; private Quaternion leftOpenRotation; private Quaternion rightOpenRotation; private bool isOpened = false; private bool isOpening = false; private bool isEntering = false; private void Awake() { CacheDoorRotations(); AutoFindPortalParticles(); PrepareTrigger(); PrepareStartState(); } private void CacheDoorRotations() { if (leftDoor != null) { leftClosedRotation = leftDoor.localRotation; leftOpenRotation = leftClosedRotation * Quaternion.Euler(0f, leftOpenAngleY, 0f); } if (rightDoor != null) { rightClosedRotation = rightDoor.localRotation; rightOpenRotation = rightClosedRotation * Quaternion.Euler(0f, rightOpenAngleY, 0f); } } private void AutoFindPortalParticles() { if ((portalParticles == null || portalParticles.Length == 0) && portalEffectRoot != null) { portalParticles = portalEffectRoot.GetComponentsInChildren(true); } } private void PrepareTrigger() { if (gateTrigger != null) { gateTrigger.enabled = false; gateTrigger.isTrigger = true; } Rigidbody rb = GetComponent(); if (rb == null) { rb = gameObject.AddComponent(); } rb.isKinematic = true; rb.useGravity = false; } private void PrepareStartState() { if (hideGateOnStart && gateVisualRoot != null) { gateVisualRoot.SetActive(false); } if (hidePortalOnStart && portalEffectRoot != null) { portalEffectRoot.SetActive(false); } } public void OpenGate() { if (isOpened || isOpening) { return; } StartCoroutine(OpenGateRoutine()); } private IEnumerator OpenGateRoutine() { isOpening = true; if (openParticle != null) { openParticle.Stop(true, ParticleSystemStopBehavior.StopEmittingAndClear); openParticle.Play(); } if (openSound != null) { openSound.Play(); } yield return new WaitForSeconds(openDelay); if (gateVisualRoot != null) { gateVisualRoot.SetActive(true); } float timer = 0f; bool portalShown = false; while (timer < openDuration) { timer += Time.deltaTime; float t = Mathf.Clamp01(timer / openDuration); t = Mathf.SmoothStep(0f, 1f, t); if (leftDoor != null) { leftDoor.localRotation = Quaternion.Slerp(leftClosedRotation, leftOpenRotation, t); } if (rightDoor != null) { rightDoor.localRotation = Quaternion.Slerp(rightClosedRotation, rightOpenRotation, t); } if (!portalShown && timer >= portalShowDelay) { ShowPortal(); portalShown = true; } yield return null; } if (leftDoor != null) { leftDoor.localRotation = leftOpenRotation; } if (rightDoor != null) { rightDoor.localRotation = rightOpenRotation; } ShowPortal(); if (gateTrigger != null) { gateTrigger.enabled = true; } isOpened = true; isOpening = false; Debug.Log("°ÔÀÌÆ® ¿­¸² ¿Ï·á"); } private void ShowPortal() { if (portalEffectRoot != null && !portalEffectRoot.activeSelf) { portalEffectRoot.SetActive(true); } if (portalParticles == null) { return; } foreach (ParticleSystem particle in portalParticles) { if (particle != null && !particle.isPlaying) { particle.Play(); } } } private void OnTriggerEnter(Collider other) { if (!isOpened || isEntering) { return; } if (!IsPlayer(other)) { return; } StartCoroutine(EnterGateRoutine()); } private bool IsPlayer(Collider other) { if (other.CompareTag(playerTag)) { return true; } if (other.transform.root.CompareTag(playerTag)) { return true; } return false; } private IEnumerator EnterGateRoutine() { isEntering = true; yield return new WaitForSeconds(sceneMoveDelay); string nextSceneName = GetNextSceneName(); if (string.IsNullOrEmpty(nextSceneName)) { Debug.LogWarning("´ÙÀ½ ¾À À̸§ÀÌ ºñ¾îÀÖ½À´Ï´Ù."); isEntering = false; yield break; } if (SceneLoadManager.Instance == null) { Debug.LogError("SceneLoadManager°¡ ¾ø½À´Ï´Ù."); isEntering = false; yield break; } Debug.Log("°ÔÀÌÆ® ÁøÀÔ, À̵¿ÇÒ ¾À: " + nextSceneName); SceneLoadManager.Instance.RequestSceneChange(nextSceneName); } private string GetNextSceneName() { if (useRandomScene && RandomSceneRouteManager.Instance != null) { return RandomSceneRouteManager.Instance.GetNextSceneName(); } return fallbackSceneName; } public void CloseGateImmediately() { StopAllCoroutines(); isOpened = false; isOpening = false; isEntering = false; if (leftDoor != null) { leftDoor.localRotation = leftClosedRotation; } if (rightDoor != null) { rightDoor.localRotation = rightClosedRotation; } if (portalEffectRoot != null) { portalEffectRoot.SetActive(false); } if (gateTrigger != null) { gateTrigger.enabled = false; } if (openParticle != null) { openParticle.Stop(true, ParticleSystemStopBehavior.StopEmittingAndClear); } if (hideGateOnStart && gateVisualRoot != null) { gateVisualRoot.SetActive(false); } } }