코드 리팩토링

재사용성 및 확장성을 고려하여 코드 전반을 리팩토링함
This commit is contained in:
2026-01-21 01:45:15 +09:00
parent b4ac8f600f
commit db5db4b106
45 changed files with 2775 additions and 248 deletions

View File

@@ -0,0 +1,215 @@
using System;
using System.Collections;
using UnityEngine;
/// <summary>
/// Reusable action execution system with busy state management.
/// Replaces repeated coroutine busy-state patterns across the codebase.
/// </summary>
public class ActionExecutor : MonoBehaviour
{
public bool IsBusy { get; private set; }
private Coroutine _currentAction;
/// <summary>
/// Event fired when an action starts.
/// </summary>
public event Action OnActionStarted;
/// <summary>
/// Event fired when an action completes.
/// </summary>
public event Action OnActionCompleted;
/// <summary>
/// Event fired when an action is cancelled.
/// </summary>
public event Action OnActionCancelled;
/// <summary>
/// Try to execute an action. Returns false if already busy.
/// </summary>
/// <param name="request">The action request to execute</param>
/// <returns>True if action started, false if busy</returns>
public bool TryExecute(ActionRequest request)
{
if (IsBusy) return false;
_currentAction = StartCoroutine(ExecuteRoutine(request));
return true;
}
/// <summary>
/// Cancel the current action if one is running.
/// </summary>
public void Cancel()
{
if (_currentAction != null)
{
StopCoroutine(_currentAction);
_currentAction = null;
IsBusy = false;
OnActionCancelled?.Invoke();
}
}
/// <summary>
/// Force reset the busy state. Use with caution.
/// </summary>
public void ForceReset()
{
if (_currentAction != null)
{
StopCoroutine(_currentAction);
_currentAction = null;
}
IsBusy = false;
}
private IEnumerator ExecuteRoutine(ActionRequest request)
{
IsBusy = true;
OnActionStarted?.Invoke();
// Pre-action callback
request.OnStart?.Invoke();
// Animation trigger
if (request.Animator != null && !string.IsNullOrEmpty(request.AnimTrigger))
{
if (request.AnimSpeed > 0)
{
request.Animator.SetFloat("ActionSpeed", request.AnimSpeed);
}
request.Animator.SetTrigger(request.AnimTrigger);
}
// Wait for impact point
if (request.ImpactDelay > 0)
{
float adjustedDelay = request.AnimSpeed > 0
? request.ImpactDelay / request.AnimSpeed
: request.ImpactDelay;
yield return new WaitForSeconds(adjustedDelay);
}
// Execute main effect
request.OnImpact?.Invoke();
// Wait for remaining duration
float remainingTime = request.TotalDuration - request.ImpactDelay;
if (request.AnimSpeed > 0)
{
remainingTime /= request.AnimSpeed;
}
if (remainingTime > 0)
{
yield return new WaitForSeconds(remainingTime);
}
// Completion callback
request.OnComplete?.Invoke();
IsBusy = false;
_currentAction = null;
OnActionCompleted?.Invoke();
}
}
/// <summary>
/// Configuration for an action to be executed by ActionExecutor.
/// </summary>
[Serializable]
public struct ActionRequest
{
/// <summary>
/// Animator to trigger animations on.
/// </summary>
public Animator Animator;
/// <summary>
/// Animation trigger name.
/// </summary>
public string AnimTrigger;
/// <summary>
/// Animation playback speed multiplier.
/// </summary>
public float AnimSpeed;
/// <summary>
/// Time delay before the impact/effect happens (for syncing with animation).
/// </summary>
public float ImpactDelay;
/// <summary>
/// Total duration of the action.
/// </summary>
public float TotalDuration;
/// <summary>
/// Callback invoked when action starts.
/// </summary>
public Action OnStart;
/// <summary>
/// Callback invoked at the impact moment.
/// </summary>
public Action OnImpact;
/// <summary>
/// Callback invoked when action completes.
/// </summary>
public Action OnComplete;
/// <summary>
/// Create a simple action request with just timing.
/// </summary>
public static ActionRequest Simple(float duration, Action onComplete)
{
return new ActionRequest
{
TotalDuration = duration,
AnimSpeed = 1f,
OnComplete = onComplete
};
}
/// <summary>
/// Create an animated action request.
/// </summary>
public static ActionRequest Animated(Animator animator, string trigger, float duration,
float impactDelay, Action onImpact, float speed = 1f)
{
return new ActionRequest
{
Animator = animator,
AnimTrigger = trigger,
AnimSpeed = speed,
ImpactDelay = impactDelay,
TotalDuration = duration,
OnImpact = onImpact
};
}
/// <summary>
/// Create a full action request with all callbacks.
/// </summary>
public static ActionRequest Full(Animator animator, string trigger, float duration,
float impactDelay, float speed, Action onStart, Action onImpact, Action onComplete)
{
return new ActionRequest
{
Animator = animator,
AnimTrigger = trigger,
AnimSpeed = speed,
ImpactDelay = impactDelay,
TotalDuration = duration,
OnStart = onStart,
OnImpact = onImpact,
OnComplete = onComplete
};
}
}