Files
WhaleAdventure_VR/Assets/My project/Fishing Scripts/UI/FishingStartTrigger.cs
2026-06-25 17:39:42 +09:00

245 lines
6.9 KiB
C#

using UnityEngine;
using UnityEngine.InputSystem;
/// <summary>
/// 낚시터 시작 영역에 붙이는 스크립트입니다.
/// 플레이어가 Trigger 영역 안에 들어오면 안내 UI를 켜고,
/// 지정한 Start Action 입력이 들어오면 FishingGameManager.StartFishing()을 호출합니다.
/// 필요하면 낚싯대를 잡고 있을 때만 시작되도록 제한할 수 있습니다.
/// </summary>
[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<Collider>();
if (col != null)
col.isTrigger = true;
}
private void Awake()
{
Collider col = GetComponent<Collider>();
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();
}
/// <summary>
/// UI 버튼이나 다른 스크립트에서도 호출할 수 있는 낚시 시작 함수입니다.
/// </summary>
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);
}
}