diff --git a/Assets/_DDD/_Scripts/GameEvent/IInteractable.cs b/Assets/_DDD/_Scripts/GameEvent/IInteractable.cs index 09ad1dd15..dbb465fa8 100644 --- a/Assets/_DDD/_Scripts/GameEvent/IInteractable.cs +++ b/Assets/_DDD/_Scripts/GameEvent/IInteractable.cs @@ -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(); } } diff --git a/Assets/_DDD/_Scripts/RestaurantCharacter/Player/RestaurantPlayerInteraction.cs b/Assets/_DDD/_Scripts/RestaurantCharacter/Player/RestaurantPlayerInteraction.cs index aa886d0dd..5b86b5206 100644 --- a/Assets/_DDD/_Scripts/RestaurantCharacter/Player/RestaurantPlayerInteraction.cs +++ b/Assets/_DDD/_Scripts/RestaurantCharacter/Player/RestaurantPlayerInteraction.cs @@ -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); } } diff --git a/Assets/_DDD/_Scripts/RestaurantCharacter/RestaurantCharacterInteraction.cs b/Assets/_DDD/_Scripts/RestaurantCharacter/RestaurantCharacterInteraction.cs index 014f8acd4..f706014b9 100644 --- a/Assets/_DDD/_Scripts/RestaurantCharacter/RestaurantCharacterInteraction.cs +++ b/Assets/_DDD/_Scripts/RestaurantCharacter/RestaurantCharacterInteraction.cs @@ -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 _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(); - if (interactable == null || !interactable.CanInteract()) continue; + var col = _nearColliders[i]; + if (col.TryGetComponent(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; + } } } diff --git a/Assets/_DDD/_Scripts/RestaurantEvent/RestaurantInteractionEvents.cs b/Assets/_DDD/_Scripts/RestaurantEvent/RestaurantInteractionEvents.cs index c69a58221..2f86f12c3 100644 --- a/Assets/_DDD/_Scripts/RestaurantEvent/RestaurantInteractionEvents.cs +++ b/Assets/_DDD/_Scripts/RestaurantEvent/RestaurantInteractionEvents.cs @@ -13,7 +13,8 @@ public static class RestaurantInteractionEventSolvers { public static Dictionary TypeToSolver = new() { - {InteractionType.RestaurantManagementUi, typeof(RestaurantManagementUiEventSolver)} + {InteractionType.RestaurantManagementUi, typeof(RestaurantManagementUiEventSolver)}, + {InteractionType.OpenRestaurant, typeof(RestaurantOpenEventSolver)} }; } diff --git a/Assets/_DDD/_Scripts/RestaurantEvent/RestaurantManagementUiEventSolver.cs b/Assets/_DDD/_Scripts/RestaurantEvent/RestaurantManagementUiEventSolver.cs index 751a9fdfb..6407cdb0e 100644 --- a/Assets/_DDD/_Scripts/RestaurantEvent/RestaurantManagementUiEventSolver.cs +++ b/Assets/_DDD/_Scripts/RestaurantEvent/RestaurantManagementUiEventSolver.cs @@ -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; diff --git a/Assets/_DDD/_Scripts/RestaurantEvent/RestaurantOpenEventSolver.cs b/Assets/_DDD/_Scripts/RestaurantEvent/RestaurantOpenEventSolver.cs index b6b5dd398..0ea0c75fa 100644 --- a/Assets/_DDD/_Scripts/RestaurantEvent/RestaurantOpenEventSolver.cs +++ b/Assets/_DDD/_Scripts/RestaurantEvent/RestaurantOpenEventSolver.cs @@ -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(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(); } } } \ No newline at end of file