245 lines
6.9 KiB
C#
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);
|
|
}
|
|
}
|