using UnityEngine; using UnityEngine.InputSystem; /// /// 낚시터 시작 영역에 붙이는 스크립트입니다. /// 플레이어가 Trigger 영역 안에 들어오면 안내 UI를 켜고, /// 지정한 Start Action 입력이 들어오면 FishingGameManager.StartFishing()을 호출합니다. /// 필요하면 낚싯대를 잡고 있을 때만 시작되도록 제한할 수 있습니다. /// [RequireComponent(typeof(Collider))] public class FishingStartTrigger : MonoBehaviour { [Header("References")] [Tooltip("낚시 미니게임을 제어하는 FishingGameManager입니다.")] [SerializeField] private FishingGameManager fishingGameManager; [Tooltip("낚시터 근처에 들어왔을 때 보여줄 시작 안내 UI입니다.")] [SerializeField] private GameObject startGuideUI; [Header("Input")] [Tooltip("낚시 시작 입력입니다. 예: XRI RightHand / Primary Button. SubmitAction과 같은 버튼은 피하는 것을 추천합니다.")] [SerializeField] private InputActionReference startAction; [Tooltip("Input Action Manager가 없거나 액션이 자동 활성화되지 않으면 켜두세요.")] [SerializeField] private bool enableInputActionManually = true; [Header("Player Check")] [Tooltip("플레이어 루트 오브젝트의 태그입니다. 보통 XR Origin에 Player 태그를 붙입니다.")] [SerializeField] private string playerTag = "Player"; [Tooltip("태그 체크를 끄고 모든 Collider 진입을 플레이어로 취급합니다. 테스트용입니다.")] [SerializeField] private bool ignorePlayerTagForTest = false; [Header("Rod Requirement")] [Tooltip("켜면 낚싯대를 잡고 있을 때만 낚시를 시작할 수 있습니다.")] [SerializeField] private bool requireRodHeld = false; [Tooltip("낚싯대에 붙어 있는 FishingRodState입니다.")] [SerializeField] private FishingRodState requiredRod; [Header("Rules")] [Tooltip("플레이어가 영역에서 나가면 낚시를 중단하고 UI를 숨깁니다. VR에서는 처음에 Off 추천.")] [SerializeField] private bool stopFishingOnExit = false; [Tooltip("낚시가 시작되면 시작 안내 UI를 숨깁니다.")] [SerializeField] private bool hideGuideWhenFishingStarts = true; [Tooltip("기억의 조각을 이미 획득한 뒤에도 다시 시작할 수 있게 합니다.")] [SerializeField] private bool allowRestartAfterClear = false; [Header("Debug")] [SerializeField] private bool showDebugLog = true; private bool playerInside; private bool actionWasEnabled; public bool PlayerInside => playerInside; private void Reset() { Collider col = GetComponent(); if (col != null) col.isTrigger = true; } private void Awake() { Collider col = GetComponent(); if (col != null && !col.isTrigger) col.isTrigger = true; SetGuideVisible(false); } private void OnEnable() { RegisterStartAction(); } private void OnDisable() { UnregisterStartAction(); } private void OnTriggerEnter(Collider other) { if (!IsPlayer(other)) return; playerInside = true; RefreshGuide(); if (showDebugLog) Debug.Log("낚시 시작 영역 진입"); } private void OnTriggerExit(Collider other) { if (!IsPlayer(other)) return; playerInside = false; SetGuideVisible(false); if (stopFishingOnExit && fishingGameManager != null) fishingGameManager.StopFishing(true); if (showDebugLog) Debug.Log("낚시 시작 영역 이탈"); } private bool IsPlayer(Collider other) { if (ignorePlayerTagForTest) return true; if (other == null) return false; if (other.CompareTag(playerTag)) return true; Transform current = other.transform; while (current != null) { if (current.CompareTag(playerTag)) return true; current = current.parent; } return false; } private void RegisterStartAction() { if (startAction == null || startAction.action == null) return; actionWasEnabled = startAction.action.enabled; startAction.action.performed += OnStartAction; if (enableInputActionManually && !actionWasEnabled) startAction.action.Enable(); } private void UnregisterStartAction() { if (startAction == null || startAction.action == null) return; startAction.action.performed -= OnStartAction; if (enableInputActionManually && !actionWasEnabled) startAction.action.Disable(); } private void OnStartAction(InputAction.CallbackContext context) { TryStartFishing(); } /// /// UI 버튼이나 다른 스크립트에서도 호출할 수 있는 낚시 시작 함수입니다. /// public void TryStartFishing() { if (!CanStartFishing()) return; fishingGameManager.StartFishing(); if (hideGuideWhenFishingStarts) SetGuideVisible(false); if (showDebugLog) Debug.Log("낚시 시작 요청 완료"); } public bool CanStartFishing() { if (!playerInside) return false; if (fishingGameManager == null) { if (showDebugLog) Debug.LogWarning("FishingStartTrigger: FishingGameManager가 연결되지 않았습니다."); return false; } if (fishingGameManager.IsActiveGame) return false; if (fishingGameManager.IsMemoryPieceCollected && !allowRestartAfterClear) return false; if (requireRodHeld) { if (requiredRod == null) { if (showDebugLog) Debug.LogWarning("FishingStartTrigger: Require Rod Held가 켜져 있지만 Required Rod가 연결되지 않았습니다."); return false; } if (!requiredRod.IsHeld) return false; } return true; } public void RefreshGuide() { if (!playerInside) { SetGuideVisible(false); return; } if (fishingGameManager != null && fishingGameManager.IsMemoryPieceCollected && !allowRestartAfterClear) { SetGuideVisible(false); return; } if (fishingGameManager != null && fishingGameManager.IsActiveGame) { SetGuideVisible(false); return; } SetGuideVisible(true); } private void SetGuideVisible(bool visible) { if (startGuideUI != null) startGuideUI.SetActive(visible); } }