diff --git a/Assets/_DDD/_Scripts/GameEvent/GameEvents.cs b/Assets/_DDD/_Scripts/GameEvent/GameEvents.cs index e4c342f34..8de0c5e22 100644 --- a/Assets/_DDD/_Scripts/GameEvent/GameEvents.cs +++ b/Assets/_DDD/_Scripts/GameEvent/GameEvents.cs @@ -77,7 +77,7 @@ public class InventoryChangedEvent : IEvent public int NewCount; } - #region RestaurantEvents + #region RestaurantInteractionEvents public class ItemSlotSelectedEvent : IEvent { diff --git a/Assets/_DDD/_Scripts/GameEvent/IInteractable.cs b/Assets/_DDD/_Scripts/GameEvent/IInteractable.cs index aea4ee1c7..4cbcd82c8 100644 --- a/Assets/_DDD/_Scripts/GameEvent/IInteractable.cs +++ b/Assets/_DDD/_Scripts/GameEvent/IInteractable.cs @@ -1,4 +1,3 @@ -using System.Collections.Generic; using UnityEngine; namespace DDD @@ -6,7 +5,7 @@ namespace DDD public enum InteractionType { None, - RestaurantManagement, + RestaurantManagementUi, Count } public interface IInteractable @@ -16,6 +15,7 @@ public interface IInteractable InteractionType GetInteractionType(); GameObject GetInteractableGameObject(); void InitializeInteraction(InteractionType interactionType); + float GetRequiredHoldTime(); } public interface IInteractor { @@ -24,6 +24,6 @@ public interface IInteractor public interface IInteractionSolver { - bool ExecuteInteraction(IInteractor interactor, ScriptableObject interactionPayloadSo = null); + bool ExecuteInteraction(IInteractor interactor, IInteractable interactable, ScriptableObject interactionPayloadSo = null); } } diff --git a/Assets/_DDD/_Scripts/InputSystem/InputManager.cs b/Assets/_DDD/_Scripts/InputSystem/InputManager.cs index c88cd36b5..4a8f1b851 100644 --- a/Assets/_DDD/_Scripts/InputSystem/InputManager.cs +++ b/Assets/_DDD/_Scripts/InputSystem/InputManager.cs @@ -28,7 +28,8 @@ public enum RestaurantActions None = 0, Move = 1 << 0, Dash = 1 << 1, - OpenManagementUi = 1 << 2, + Interact = 1 << 2, + OpenManagementUi = 1 << 3, } [Flags] diff --git a/Assets/_DDD/_Scripts/RestaurantCharacter/RestaurantCharacter.cs b/Assets/_DDD/_Scripts/RestaurantCharacter/RestaurantCharacter.cs index d21eddc31..33aae44a9 100644 --- a/Assets/_DDD/_Scripts/RestaurantCharacter/RestaurantCharacter.cs +++ b/Assets/_DDD/_Scripts/RestaurantCharacter/RestaurantCharacter.cs @@ -1,5 +1,3 @@ -using DDD.RestaurantEvent; -using NUnit.Framework; using UnityEngine; namespace DDD @@ -8,13 +6,12 @@ public class RestaurantCharacter : MonoBehaviour, IGameCharacter, IInteractor { private void Start() { - //TODO_IMPLEMENT_ME(); // TODO : Add event solvers dynamically - for (int i = (int)InteractionType.Count; i < (int)InteractionType.Count; i++) + for (int i = 0; i < (int)InteractionType.Count; i++) { InteractionType interactionType = (InteractionType)i; // TODO : if this character should handle the interaction? - if(RestaurantEventSolvers.TypeToSolver.TryGetValue(interactionType, out var solverType)) + if (RestaurantInteractionEventSolvers.TypeToSolver.TryGetValue(interactionType, out var solverType)) { gameObject.AddComponent(solverType); } @@ -23,8 +20,7 @@ private void Start() public GameObject GetInteractorGameObject() { - // TODO : TODO_IMPLEMENT_ME - return null; + return gameObject; } } } \ No newline at end of file diff --git a/Assets/_DDD/_Scripts/RestaurantCharacter/RestaurantCharacterInteraction.cs b/Assets/_DDD/_Scripts/RestaurantCharacter/RestaurantCharacterInteraction.cs index f996a0bd7..5f192493f 100644 --- a/Assets/_DDD/_Scripts/RestaurantCharacter/RestaurantCharacterInteraction.cs +++ b/Assets/_DDD/_Scripts/RestaurantCharacter/RestaurantCharacterInteraction.cs @@ -1,13 +1,65 @@ -using DDD.RestaurantEvent; +using System.Threading.Tasks; +using Sirenix.OdinInspector; using UnityEngine; +using UnityEngine.InputSystem; namespace DDD { public class RestaurantCharacterInteraction : MonoBehaviour, IInteractor, IEventHandler { + private RestaurantPlayerDataSo _restaurantPlayerDataSo; + + [ReadOnly, SerializeField] private Collider[] _nearColliders = new Collider[10]; + private IInteractable _nearestInteractable; + + private float _interactHeldTime; + private bool _isInteracting; + private void Start() { - EventBus.Register(this); + _ = Initialize(); + } + + private void Update() + { + if (!_restaurantPlayerDataSo) return; + + _nearestInteractable = GetNearestInteractable(); + + if (_isInteracting && _nearestInteractable != null) + { + _interactHeldTime += Time.deltaTime; + + if (_interactHeldTime >= _nearestInteractable.GetRequiredHoldTime()) + { + _isInteracting = false; + _nearestInteractable.OnInteracted(this); + } + } + } + + private void OnDestroy() + { + EventBus.Unregister(this); + + if (_restaurantPlayerDataSo) + { + _restaurantPlayerDataSo.InteractAction.performed -= OnInteractPerformed; + _restaurantPlayerDataSo.InteractAction.canceled -= OnInteractCanceled; + } + } + + private async Task Initialize() + { + _restaurantPlayerDataSo = await AssetManager.LoadAsset(DataConstants.RestaurantPlayerDataSo); + Debug.Assert(_restaurantPlayerDataSo != null, "_restaurantPlayerDataSo is null"); + + _restaurantPlayerDataSo.InteractAction = InputManager.Instance.GetAction(InputActionMaps.Restaurant, nameof(RestaurantActions.Interact)); + + _restaurantPlayerDataSo.InteractAction.performed += OnInteractPerformed; + _restaurantPlayerDataSo.InteractAction.canceled += OnInteractCanceled; + + EventBus.Register(this); } public void Invoke(RestaurantInteractionEvent evt) @@ -17,8 +69,54 @@ public void Invoke(RestaurantInteractionEvent evt) public GameObject GetInteractorGameObject() { - // TODO : TODO_IMPLEMENT_ME - return null; + return gameObject; + } + + private void OnInteractPerformed(InputAction.CallbackContext context) + { + if (_nearestInteractable == null || _nearestInteractable.CanInteract() == false) return; + + float requiredHoldTime = _nearestInteractable.GetRequiredHoldTime(); + + if (requiredHoldTime <= 0f) + { + _nearestInteractable.OnInteracted(this); + } + else + { + _isInteracting = true; + _interactHeldTime = 0f; + } + } + + private void OnInteractCanceled(InputAction.CallbackContext context) + { + _isInteracting = false; + _interactHeldTime = 0f; + } + + private IInteractable GetNearestInteractable() + { + int nearColliderCount = Physics.OverlapSphereNonAlloc(transform.position, _restaurantPlayerDataSo.InteractionRadius, + _nearColliders, _restaurantPlayerDataSo.InteractionLayerMask, QueryTriggerInteraction.Collide); + + IInteractable nearestInteractable = null; + float minDistance = float.MaxValue; + + for (int i = 0; i < nearColliderCount; i++) + { + var interactable = _nearColliders[i].GetComponent(); + if (interactable == null || interactable.CanInteract() == false) continue; + + float sqrMagnitude = (interactable.GetInteractableGameObject().transform.position - transform.position).sqrMagnitude; + if (sqrMagnitude > minDistance) continue; + + nearestInteractable = interactable; + minDistance = sqrMagnitude; + } + + print(nearestInteractable?.GetInteractableGameObject().name); + return nearestInteractable; } } } \ No newline at end of file diff --git a/Assets/_DDD/_Scripts/RestaurantCharacter/RestaurantPlayerDataSo.cs b/Assets/_DDD/_Scripts/RestaurantCharacter/RestaurantPlayerDataSo.cs index b962a70e7..4de84246d 100644 --- a/Assets/_DDD/_Scripts/RestaurantCharacter/RestaurantPlayerDataSo.cs +++ b/Assets/_DDD/_Scripts/RestaurantCharacter/RestaurantPlayerDataSo.cs @@ -28,6 +28,9 @@ public class RestaurantPlayerDataSo : ScriptableObject public float BoxCastExtentScale = 0.95f; public float MinSlideFactorThreshold = 0.05f; + public float InteractionRadius = 1f; + public LayerMask InteractionLayerMask; + // 디버그 public int InputLineSortingOrder = 10; public int VelocityLineSortingOrder = 9; @@ -41,6 +44,7 @@ public class RestaurantPlayerDataSo : ScriptableObject public InputAction MoveAction; public InputAction DashAction; + public InputAction InteractAction; public InputAction OpenManagementUiAction; } } \ No newline at end of file diff --git a/Assets/_DDD/_Scripts/RestaurantEnvironment/RestaurantEnvironment.cs b/Assets/_DDD/_Scripts/RestaurantEnvironment/RestaurantEnvironment.cs index 9c333240d..9cf48dce2 100644 --- a/Assets/_DDD/_Scripts/RestaurantEnvironment/RestaurantEnvironment.cs +++ b/Assets/_DDD/_Scripts/RestaurantEnvironment/RestaurantEnvironment.cs @@ -1,4 +1,3 @@ -using DDD.RestaurantEvent; using Spine.Unity; using Unity.VisualScripting; using UnityEngine; diff --git a/Assets/_DDD/_Scripts/RestaurantEvent/RestaurantEventSolver.cs b/Assets/_DDD/_Scripts/RestaurantEvent/RestaurantEventSolver.cs deleted file mode 100644 index a213611c7..000000000 --- a/Assets/_DDD/_Scripts/RestaurantEvent/RestaurantEventSolver.cs +++ /dev/null @@ -1,13 +0,0 @@ -using UnityEngine; - -namespace DDD.RestaurantEvent -{ - public class RestaurantManagementEventSolver : MonoBehaviour, IInteractionSolver - { - public bool ExecuteInteraction(IInteractor interactor, ScriptableObject interactionPayloadSo = null) - { - // TODO : TODO_IMPLEMENT_ME - return false; - } - } -} \ No newline at end of file diff --git a/Assets/_DDD/_Scripts/RestaurantEvent/RestaurantInteractionComponent.cs b/Assets/_DDD/_Scripts/RestaurantEvent/RestaurantInteractionComponent.cs index 475e7dde9..cd9c070b7 100644 --- a/Assets/_DDD/_Scripts/RestaurantEvent/RestaurantInteractionComponent.cs +++ b/Assets/_DDD/_Scripts/RestaurantEvent/RestaurantInteractionComponent.cs @@ -1,9 +1,12 @@ using UnityEngine; -namespace DDD.RestaurantEvent +namespace DDD { public class RestaurantInteractionComponent : MonoBehaviour, IInteractable { + [SerializeField] private InteractionType _interactionType = InteractionType.None; + [SerializeField] private float _holdTime = 1f; + public bool CanInteract() { return true; @@ -15,27 +18,29 @@ public bool OnInteracted(IInteractor interactor, ScriptableObject interactionPay { return false; } - - bool interactionResult = RestaurantEvents.RestaurantInteraction.RequestInteraction(interactor.GetInteractorGameObject(), + bool interactionResult = RestaurantInteractionEvents.RestaurantInteraction.RequestInteraction(interactor.GetInteractorGameObject(), GetInteractableGameObject(), GetInteractionType(), interactionPayloadSo, true); return interactionResult; } public InteractionType GetInteractionType() { - // TODO : TODO_IMPLEMENT_ME - return InteractionType.None; + return _interactionType; } public GameObject GetInteractableGameObject() { - // TODO : TODO_IMPLEMENT_ME - return null; + return gameObject; } public void InitializeInteraction(InteractionType interactionType) { - // TODO : TODO_IMPLEMENT_ME + _interactionType = interactionType; + } + + public float GetRequiredHoldTime() + { + return _holdTime; } } } \ No newline at end of file diff --git a/Assets/_DDD/_Scripts/RestaurantEvent/RestaurantEvents.cs b/Assets/_DDD/_Scripts/RestaurantEvent/RestaurantInteractionEvents.cs similarity index 74% rename from Assets/_DDD/_Scripts/RestaurantEvent/RestaurantEvents.cs rename to Assets/_DDD/_Scripts/RestaurantEvent/RestaurantInteractionEvents.cs index d7bc45625..c69a58221 100644 --- a/Assets/_DDD/_Scripts/RestaurantEvent/RestaurantEvents.cs +++ b/Assets/_DDD/_Scripts/RestaurantEvent/RestaurantInteractionEvents.cs @@ -2,18 +2,18 @@ using System.Collections.Generic; using UnityEngine; -namespace DDD.RestaurantEvent +namespace DDD { - public static class RestaurantEvents + public static class RestaurantInteractionEvents { public static RestaurantInteractionEvent RestaurantInteraction = new(); } - public static class RestaurantEventSolvers + public static class RestaurantInteractionEventSolvers { public static Dictionary TypeToSolver = new() { - {InteractionType.RestaurantManagement, typeof(RestaurantManagementEventSolver)} + {InteractionType.RestaurantManagementUi, typeof(RestaurantManagementUiEventSolver)} }; } @@ -23,7 +23,7 @@ public class RestaurantInteractionEvent : IEvent public GameObject Target; public InteractionType InteractionType; public ScriptableObject InteractionPayloadSo; - public bool eventResult = false; + public bool EventResult = false; public RestaurantInteractionEvent MakeInteractionEvent(GameObject causer, GameObject target, InteractionType interactionType, ScriptableObject interactionPayloadSo) @@ -41,18 +41,19 @@ public bool RequestInteraction(GameObject causer, GameObject target, Interaction } var evt = MakeInteractionEvent(causer, target, interactionType, interactionPayloadSo); - evt.eventResult = false; + evt.EventResult = false; // Solve event directly. 이벤트 처리는 여기서 하고, 이벤트 호출로는 이런 이벤트가 호출되었고 결과가 어떻다는 거 전파하는 식으로. - if (RestaurantEventSolvers.TypeToSolver.TryGetValue(interactionType, out var solverType)) + if (RestaurantInteractionEventSolvers.TypeToSolver.TryGetValue(interactionType, out var solverType)) { - Component solverComponent = target.GetComponent(solverType); + Component solverComponent = causer.GetComponent(solverType); IInteractionSolver solver = solverComponent as IInteractionSolver; IInteractor interactor = causer.GetComponent(); + IInteractable interactable = target.GetComponent(); // Cast solverComponent to IInteractable if (solver is not null && interactor is not null) { - evt.eventResult = solver.ExecuteInteraction(interactor, interactionPayloadSo); + evt.EventResult = solver.ExecuteInteraction(interactor, interactable, interactionPayloadSo); } else { @@ -62,7 +63,7 @@ public bool RequestInteraction(GameObject causer, GameObject target, Interaction } EventBus.Broadcast(evt);// 이벤트 결과를 이거 받아서 처리하면 될듯. - return evt.eventResult; + return evt.EventResult; } } } \ No newline at end of file diff --git a/Assets/_DDD/_Scripts/RestaurantEvent/RestaurantManagementUiEventSolver.cs b/Assets/_DDD/_Scripts/RestaurantEvent/RestaurantManagementUiEventSolver.cs new file mode 100644 index 000000000..50f1c83ef --- /dev/null +++ b/Assets/_DDD/_Scripts/RestaurantEvent/RestaurantManagementUiEventSolver.cs @@ -0,0 +1,17 @@ +using UnityEngine; + +namespace DDD +{ + public class RestaurantManagementUiEventSolver : MonoBehaviour, IInteractionSolver + { + public bool ExecuteInteraction(IInteractor interactor, IInteractable interactable, ScriptableObject interactionPayloadSo = null) + { + GameFlowState currentGameFlowState = GameFlowManager.Instance.GameFlowDataSo.CurrentGameState; + if (currentGameFlowState != GameFlowState.ReadyForRestaurant) return false; + var evt = GameEvents.OpenPopupUiEvent; + evt.UiType = typeof(RestaurantManagementUi); + EventBus.Broadcast(evt); + return true; + } + } +} \ No newline at end of file