2026-06-19 UI, UI로직
This commit is contained in:
358
Assets/My project/Fishing Scripts/UI/FishingGameManager.cs
Normal file
358
Assets/My project/Fishing Scripts/UI/FishingGameManager.cs
Normal file
@@ -0,0 +1,358 @@
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
|
||||
public class FishingGameManager : MonoBehaviour
|
||||
{
|
||||
public enum ResultType
|
||||
{
|
||||
Perfect,
|
||||
Good,
|
||||
Miss
|
||||
}
|
||||
|
||||
[Header("References")]
|
||||
[SerializeField] private FishingGaugeUI ui;
|
||||
[SerializeField] private FishingRewardSystem rewardSystem;
|
||||
[SerializeField] private FishingHapticManager haptic;
|
||||
[SerializeField] private RotateUI centerIconRotate;
|
||||
|
||||
[Header("Pointer")]
|
||||
[SerializeField] private float pointerAngle;
|
||||
[SerializeField] private float pointerSpeed = 180f;
|
||||
[SerializeField] private float minSpeed = 180f;
|
||||
[SerializeField] private float maxSpeed = 450f;
|
||||
|
||||
[Header("Zone")]
|
||||
[SerializeField] private float startZoneSize = 90f;
|
||||
[SerializeField] private float zoneSize = 90f;
|
||||
[SerializeField] private float minZoneSize = 30f;
|
||||
[SerializeField] private float maxZoneSize = 120f;
|
||||
[SerializeField] private float zoneCenter;
|
||||
|
||||
[Header("Rules")]
|
||||
[SerializeField] private int requiredSuccesses = 3;
|
||||
[SerializeField] private int allowedFails = 3;
|
||||
|
||||
[Header("Round Settings")]
|
||||
[SerializeField] private float nextRoundDelay = 0.35f;
|
||||
[SerializeField] private bool randomDirectionEachRound = true;
|
||||
[SerializeField] private bool startOnAwake = true;
|
||||
|
||||
[Header("Debug")]
|
||||
[SerializeField] private bool showDebugLog = true;
|
||||
|
||||
private int successCount;
|
||||
private int failCount;
|
||||
|
||||
private bool clockwise = true;
|
||||
private bool activeGame;
|
||||
private bool inputLocked;
|
||||
|
||||
private Coroutine nextRoundRoutine;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
if (startOnAwake)
|
||||
{
|
||||
StartFishing();
|
||||
}
|
||||
else
|
||||
{
|
||||
InitializeIdleUI();
|
||||
}
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (!activeGame)
|
||||
return;
|
||||
|
||||
if (inputLocked)
|
||||
return;
|
||||
|
||||
RotatePointer();
|
||||
}
|
||||
|
||||
private void InitializeIdleUI()
|
||||
{
|
||||
if (ui != null)
|
||||
{
|
||||
ui.HideRoundResult();
|
||||
ui.HideFinalResult();
|
||||
ui.UpdateCounter(0, requiredSuccesses, 0, allowedFails);
|
||||
ui.SetPointerRotation(0f);
|
||||
ui.SetZone(0f, startZoneSize);
|
||||
}
|
||||
|
||||
if (centerIconRotate != null)
|
||||
centerIconRotate.StopRotate();
|
||||
}
|
||||
|
||||
public void StartFishing()
|
||||
{
|
||||
if (nextRoundRoutine != null)
|
||||
{
|
||||
StopCoroutine(nextRoundRoutine);
|
||||
nextRoundRoutine = null;
|
||||
}
|
||||
|
||||
successCount = 0;
|
||||
failCount = 0;
|
||||
|
||||
pointerAngle = 0f;
|
||||
pointerSpeed = minSpeed;
|
||||
zoneSize = startZoneSize;
|
||||
|
||||
activeGame = true;
|
||||
inputLocked = false;
|
||||
|
||||
clockwise = Random.value > 0.5f;
|
||||
|
||||
if (ui != null)
|
||||
{
|
||||
ui.HideRoundResult();
|
||||
ui.HideFinalResult();
|
||||
}
|
||||
|
||||
if (centerIconRotate != null)
|
||||
{
|
||||
centerIconRotate.ResetRotation();
|
||||
centerIconRotate.StartRotate();
|
||||
}
|
||||
|
||||
RandomizeZone();
|
||||
UpdateUI();
|
||||
|
||||
if (showDebugLog)
|
||||
Debug.Log("낚시 시작");
|
||||
}
|
||||
|
||||
private void RotatePointer()
|
||||
{
|
||||
float dir = clockwise ? 1f : -1f;
|
||||
|
||||
pointerAngle += dir * pointerSpeed * Time.deltaTime;
|
||||
pointerAngle = Normalize(pointerAngle);
|
||||
|
||||
if (ui != null)
|
||||
ui.SetPointerRotation(pointerAngle);
|
||||
}
|
||||
|
||||
public void SubmitAttempt()
|
||||
{
|
||||
if (!activeGame)
|
||||
return;
|
||||
|
||||
if (inputLocked)
|
||||
return;
|
||||
|
||||
inputLocked = true;
|
||||
|
||||
ResultType result = EvaluateResult();
|
||||
|
||||
switch (result)
|
||||
{
|
||||
case ResultType.Perfect:
|
||||
OnPerfect();
|
||||
break;
|
||||
|
||||
case ResultType.Good:
|
||||
OnGood();
|
||||
break;
|
||||
|
||||
case ResultType.Miss:
|
||||
OnMiss();
|
||||
break;
|
||||
}
|
||||
|
||||
if (successCount >= requiredSuccesses)
|
||||
{
|
||||
FishingSuccess();
|
||||
return;
|
||||
}
|
||||
|
||||
if (failCount >= allowedFails)
|
||||
{
|
||||
FishingFail();
|
||||
return;
|
||||
}
|
||||
|
||||
nextRoundRoutine = StartCoroutine(NextRoundRoutine());
|
||||
}
|
||||
|
||||
private ResultType EvaluateResult()
|
||||
{
|
||||
float delta = Mathf.Abs(Mathf.DeltaAngle(pointerAngle, zoneCenter));
|
||||
|
||||
float perfectRange = zoneSize * 0.2f;
|
||||
float goodRange = zoneSize * 0.5f;
|
||||
|
||||
if (delta <= perfectRange)
|
||||
return ResultType.Perfect;
|
||||
|
||||
if (delta <= goodRange)
|
||||
return ResultType.Good;
|
||||
|
||||
return ResultType.Miss;
|
||||
}
|
||||
|
||||
private void OnPerfect()
|
||||
{
|
||||
successCount++;
|
||||
|
||||
zoneSize *= 0.9f;
|
||||
pointerSpeed *= 1.05f;
|
||||
|
||||
if (haptic != null)
|
||||
haptic.Perfect();
|
||||
|
||||
if (ui != null)
|
||||
ui.ShowResult("완벽!");
|
||||
|
||||
if (showDebugLog)
|
||||
Debug.Log("낚시 판정: Perfect");
|
||||
|
||||
ClampDifficulty();
|
||||
UpdateUI();
|
||||
}
|
||||
|
||||
private void OnGood()
|
||||
{
|
||||
successCount++;
|
||||
|
||||
zoneSize *= 0.95f;
|
||||
pointerSpeed *= 1.02f;
|
||||
|
||||
if (haptic != null)
|
||||
haptic.Good();
|
||||
|
||||
if (ui != null)
|
||||
ui.ShowResult("성공!");
|
||||
|
||||
if (showDebugLog)
|
||||
Debug.Log("낚시 판정: Good");
|
||||
|
||||
ClampDifficulty();
|
||||
UpdateUI();
|
||||
}
|
||||
|
||||
private void OnMiss()
|
||||
{
|
||||
failCount++;
|
||||
|
||||
zoneSize *= 1.05f;
|
||||
pointerSpeed *= 0.95f;
|
||||
|
||||
if (haptic != null)
|
||||
haptic.Miss();
|
||||
|
||||
if (ui != null)
|
||||
ui.ShowResult("실패!");
|
||||
|
||||
if (showDebugLog)
|
||||
Debug.Log("낚시 판정: Miss");
|
||||
|
||||
ClampDifficulty();
|
||||
UpdateUI();
|
||||
}
|
||||
|
||||
private IEnumerator NextRoundRoutine()
|
||||
{
|
||||
yield return new WaitForSeconds(nextRoundDelay);
|
||||
|
||||
if (!activeGame)
|
||||
yield break;
|
||||
|
||||
if (randomDirectionEachRound)
|
||||
clockwise = Random.value > 0.5f;
|
||||
|
||||
RandomizeZone();
|
||||
UpdateUI();
|
||||
|
||||
inputLocked = false;
|
||||
nextRoundRoutine = null;
|
||||
}
|
||||
|
||||
private void ClampDifficulty()
|
||||
{
|
||||
zoneSize = Mathf.Clamp(zoneSize, minZoneSize, maxZoneSize);
|
||||
pointerSpeed = Mathf.Clamp(pointerSpeed, minSpeed, maxSpeed);
|
||||
}
|
||||
|
||||
private void RandomizeZone()
|
||||
{
|
||||
zoneCenter = Random.Range(0f, 360f);
|
||||
}
|
||||
|
||||
private void UpdateUI()
|
||||
{
|
||||
if (ui == null)
|
||||
return;
|
||||
|
||||
ui.SetZone(zoneCenter, zoneSize);
|
||||
ui.UpdateCounter(successCount, requiredSuccesses, failCount, allowedFails);
|
||||
}
|
||||
|
||||
private void FishingSuccess()
|
||||
{
|
||||
activeGame = false;
|
||||
inputLocked = true;
|
||||
|
||||
if (centerIconRotate != null)
|
||||
centerIconRotate.StopRotate();
|
||||
|
||||
if (ui != null)
|
||||
ui.ShowFinalResult("낚시 성공!");
|
||||
|
||||
if (rewardSystem != null)
|
||||
rewardSystem.GiveReward();
|
||||
|
||||
if (showDebugLog)
|
||||
Debug.Log("낚시 최종 성공");
|
||||
}
|
||||
|
||||
private void FishingFail()
|
||||
{
|
||||
activeGame = false;
|
||||
inputLocked = true;
|
||||
|
||||
if (centerIconRotate != null)
|
||||
centerIconRotate.StopRotate();
|
||||
|
||||
if (ui != null)
|
||||
ui.ShowFinalResult("낚시 실패!");
|
||||
|
||||
if (showDebugLog)
|
||||
Debug.Log("낚시 최종 실패");
|
||||
}
|
||||
|
||||
public void ResetFishing()
|
||||
{
|
||||
StartFishing();
|
||||
}
|
||||
|
||||
private float Normalize(float angle)
|
||||
{
|
||||
angle %= 360f;
|
||||
|
||||
if (angle < 0f)
|
||||
angle += 360f;
|
||||
|
||||
return angle;
|
||||
}
|
||||
|
||||
// XR Input Action의 Select / Trigger 버튼에 연결
|
||||
public void OnSubmit(InputValue value)
|
||||
{
|
||||
if (value.isPressed)
|
||||
SubmitAttempt();
|
||||
}
|
||||
|
||||
// Reset 버튼에 연결 가능
|
||||
public void OnReset(InputValue value)
|
||||
{
|
||||
if (value.isPressed)
|
||||
ResetFishing();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user