게이트 이동 시스템 추가 및 기존 이동 매니저 정리
This commit is contained in:
326
Assets/02_Scripts/Managers/change room manager/RoomExitGate.cs
Normal file
326
Assets/02_Scripts/Managers/change room manager/RoomExitGate.cs
Normal file
@@ -0,0 +1,326 @@
|
||||
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<ParticleSystem>(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void PrepareTrigger()
|
||||
{
|
||||
if (gateTrigger != null)
|
||||
{
|
||||
gateTrigger.enabled = false;
|
||||
gateTrigger.isTrigger = true;
|
||||
}
|
||||
|
||||
Rigidbody rb = GetComponent<Rigidbody>();
|
||||
|
||||
if (rb == null)
|
||||
{
|
||||
rb = gameObject.AddComponent<Rigidbody>();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user