상호작용 로직 수정

This commit is contained in:
NTG_Lenovo 2025-08-07 17:51:36 +09:00
parent 78ca575910
commit f02fe591dc
6 changed files with 58 additions and 28 deletions

View File

@ -4,8 +4,9 @@ namespace DDD
{
public enum InteractionType
{
None,
None = 0,
RestaurantManagementUi,
OpenRestaurant,
Count
}
public interface IInteractable
@ -26,6 +27,6 @@ public interface IInteractor
public interface IInteractionSolver
{
bool ExecuteInteraction(IInteractor interactor, IInteractable interactable, ScriptableObject interactionPayloadSo = null);
bool CanInteract();
bool CanExecuteInteraction();
}
}

View File

@ -63,6 +63,7 @@ private void OnInteractPerformed(InputAction.CallbackContext context)
private void OnInteractCanceled(InputAction.CallbackContext context)
{
OnInteractionHoldProgress(0f);
ResetInteractionState();
}
@ -74,10 +75,7 @@ protected override void OnNearestInteractableChanged(IInteractable newTarget)
}
else
{
if (_isInteracting == false)
{
EventBus.Broadcast(GameEvents.HideInteractionUiEvent);
}
EventBus.Broadcast(GameEvents.HideInteractionUiEvent);
}
}

View File

@ -1,3 +1,4 @@
using System.Collections.Generic;
using Sirenix.OdinInspector;
using UnityEngine;
@ -16,6 +17,7 @@ public class RestaurantCharacterInteraction : MonoBehaviour, IInteractor, IEvent
protected float _interactionRadius = 1f;
protected LayerMask _interactionLayerMask = (LayerMask)(-1);
private Dictionary<InteractionType, IInteractionSolver> _cachedSolvers = new();
protected virtual void Start() { }
@ -63,37 +65,54 @@ protected virtual void OnInteractionCompleted() { }
protected void ResetInteractionState()
{
_isInteracting = false;
_interactingTarget = null;
_interactHeldTime = 0f;
OnInteractionHoldProgress(0f);
_interactingTarget = null;
}
protected IInteractable GetNearestInteractable()
{
int nearColliderCount = Physics.OverlapSphereNonAlloc(transform.position, _interactionRadius,
_nearColliders, _interactionLayerMask, QueryTriggerInteraction.Collide);
int colliderCount = Physics.OverlapSphereNonAlloc(transform.position, _interactionRadius, _nearColliders, _interactionLayerMask);
float closestDistance = float.MaxValue;
IInteractable closest = null;
IInteractable nearest = null;
float minSqrDistance = float.MaxValue;
for (int i = 0; i < nearColliderCount; i++)
for (int i = 0; i < colliderCount; i++)
{
var interactable = _nearColliders[i].GetComponent<IInteractable>();
if (interactable == null || !interactable.CanInteract()) continue;
var col = _nearColliders[i];
if (col.TryGetComponent<IInteractable>(out var interactable) == false || interactable.CanInteract() == false) continue;
float sqrDistance = (interactable.GetInteractableGameObject().transform.position - transform.position).sqrMagnitude;
if (sqrDistance < minSqrDistance)
var type = interactable.GetInteractionType();
if (ContainTypeToSolver(type, out var solver) == false || solver.CanExecuteInteraction() == false) continue;
float distance = Vector3.Distance(transform.position, col.transform.position);
if (distance < closestDistance)
{
minSqrDistance = sqrDistance;
nearest = interactable;
closestDistance = distance;
closest = interactable;
}
}
return nearest;
return closest;
}
public virtual void Invoke(RestaurantInteractionEvent evt) { }
public GameObject GetInteractorGameObject() => gameObject;
private bool ContainTypeToSolver(InteractionType type, out IInteractionSolver solver)
{
if (_cachedSolvers.TryGetValue(type, out solver)) return solver != null;
solver = null;
if (!RestaurantInteractionEventSolvers.TypeToSolver.TryGetValue(type, out var solverType)) return false;
if (!TryGetComponent(solverType, out var component)) return false;
solver = component as IInteractionSolver;
_cachedSolvers[type] = solver;
return solver != null;
}
}
}

View File

@ -13,7 +13,8 @@ public static class RestaurantInteractionEventSolvers
{
public static Dictionary<InteractionType, Type> TypeToSolver = new()
{
{InteractionType.RestaurantManagementUi, typeof(RestaurantManagementUiEventSolver)}
{InteractionType.RestaurantManagementUi, typeof(RestaurantManagementUiEventSolver)},
{InteractionType.OpenRestaurant, typeof(RestaurantOpenEventSolver)}
};
}

View File

@ -6,7 +6,7 @@ public class RestaurantManagementUiEventSolver : MonoBehaviour, IInteractionSolv
{
public bool ExecuteInteraction(IInteractor interactor, IInteractable interactable, ScriptableObject interactionPayloadSo = null)
{
if (CanInteract() == false) return false;
if (CanExecuteInteraction() == false) return false;
var evt = GameEvents.OpenPopupUiEvent;
evt.UiType = typeof(RestaurantManagementUi);
@ -14,7 +14,7 @@ public bool ExecuteInteraction(IInteractor interactor, IInteractable interactabl
return true;
}
public bool CanInteract()
public bool CanExecuteInteraction()
{
GameFlowState currentGameFlowState = GameFlowManager.Instance.GameFlowDataSo.CurrentGameState;
return currentGameFlowState == GameFlowState.ReadyForRestaurant;

View File

@ -1,23 +1,34 @@
using System.Threading.Tasks;
using UnityEngine;
namespace DDD
{
public class RestaurantOpenEventSolver : MonoBehaviour, IInteractionSolver
{
private RestaurantManagementSo _restaurantManagementSo;
private void Start()
{
_ = Initialize();
}
private async Task Initialize()
{
_restaurantManagementSo = await AssetManager.LoadAsset<RestaurantManagementSo>(DataConstants.RestaurantManagementSo);
}
public bool ExecuteInteraction(IInteractor interactor, IInteractable interactable, ScriptableObject interactionPayloadSo = null)
{
if (CanInteract() == false) return false;
if (CanExecuteInteraction() == false) return false;
GameFlowManager.Instance.ChangeFlow(GameFlowState.RunRestaurant);
return true;
}
public bool CanInteract()
public bool CanExecuteInteraction()
{
// TODO : 영업 가능한 상태인지 조건 추가 (최소 요리, 요리도구 배치 등)
GameFlowState currentGameFlowState = GameFlowManager.Instance.GameFlowDataSo.CurrentGameState;
return currentGameFlowState == GameFlowState.ReadyForRestaurant;
return currentGameFlowState == GameFlowState.ReadyForRestaurant && _restaurantManagementSo.IsOpenable();
}
}
}