From 239ab0601a173f331ccc3e9164f390360370e562 Mon Sep 17 00:00:00 2001 From: NTG_Lenovo Date: Wed, 6 Aug 2025 17:43:41 +0900 Subject: [PATCH] =?UTF-8?q?=EC=83=81=ED=98=B8=EC=9E=91=EC=9A=A9=20?= =?UTF-8?q?=ED=81=B4=EB=9E=98=EC=8A=A4=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../RestaurantCharacterInteraction.cs | 166 +++++------------- .../RestaurantPlayerInteraction.cs | 105 +++++++++++ 2 files changed, 150 insertions(+), 121 deletions(-) create mode 100644 Assets/_DDD/_Scripts/RestaurantCharacter/RestaurantPlayerInteraction.cs diff --git a/Assets/_DDD/_Scripts/RestaurantCharacter/RestaurantCharacterInteraction.cs b/Assets/_DDD/_Scripts/RestaurantCharacter/RestaurantCharacterInteraction.cs index 585a6316f..014f8acd4 100644 --- a/Assets/_DDD/_Scripts/RestaurantCharacter/RestaurantCharacterInteraction.cs +++ b/Assets/_DDD/_Scripts/RestaurantCharacter/RestaurantCharacterInteraction.cs @@ -1,62 +1,39 @@ -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 IInteractable _previousInteractable; - private IInteractable _interactingTarget; - - private float _interactHeldTime; - private bool _isInteracting; - - private void Start() - { - _ = Initialize(); - } + [SerializeField, ReadOnly] protected Collider[] _nearColliders = new Collider[10]; - private void Update() - { - if (!_restaurantPlayerDataSo) return; + protected IInteractable _nearestInteractable; + protected IInteractable _previousInteractable; + protected IInteractable _interactingTarget; + protected float _interactHeldTime; + protected bool _isInteracting; + + protected float _interactionRadius = 1f; + protected LayerMask _interactionLayerMask = (LayerMask)(-1); + + protected virtual void Start() { } + + protected virtual void Update() + { _nearestInteractable = GetNearestInteractable(); if (_nearestInteractable != _previousInteractable) { _previousInteractable = _nearestInteractable; - - if (_nearestInteractable != null && _nearestInteractable.CanInteract()) - { - BroadcastShowUi(_nearestInteractable, 0f); - } - else - { - EventBus.Broadcast(GameEvents.HideInteractionUiEvent); - } + OnNearestInteractableChanged(_nearestInteractable); } - + if (_isInteracting) { - // 도중에 타겟이 바뀐 경우 초기화 if (_nearestInteractable != _interactingTarget) { - _isInteracting = false; - _interactHeldTime = 0f; - _interactingTarget = null; - - // UI 초기화 - if (_nearestInteractable != null && _nearestInteractable.CanInteract()) - { - BroadcastShowUi(_nearestInteractable, 0f); - } - + ResetInteractionState(); return; } @@ -67,109 +44,56 @@ private void Update() if (_interactHeldTime >= requiredHoldTime) { - ratio = 0f; _isInteracting = false; _interactingTarget.OnInteracted(this); _interactingTarget = null; + OnInteractionCompleted(); } - BroadcastShowUi(_interactingTarget, ratio); + OnInteractionHoldProgress(ratio); } } - private void OnDestroy() - { - EventBus.Unregister(this); + protected virtual void OnDestroy() { } - if (_restaurantPlayerDataSo) - { - _restaurantPlayerDataSo.InteractAction.performed -= OnInteractPerformed; - _restaurantPlayerDataSo.InteractAction.canceled -= OnInteractCanceled; - } - } + protected virtual void OnNearestInteractableChanged(IInteractable newTarget) { } + protected virtual void OnInteractionHoldProgress(float ratio) { } + protected virtual void OnInteractionCompleted() { } - 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) - { - // TODO : 이벤트결과를 보고 할 일이 있다면 여기서 뭔가 처리. 기본적으로 이벤트에서 이미 인터페이스로 인터랙션 처리됨 - } - - public GameObject GetInteractorGameObject() - { - 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; - _interactingTarget = _nearestInteractable; - } - } - - private void OnInteractCanceled(InputAction.CallbackContext context) + protected void ResetInteractionState() { _isInteracting = false; _interactHeldTime = 0f; + OnInteractionHoldProgress(0f); _interactingTarget = null; - - if (_nearestInteractable != null && _nearestInteractable.CanInteract()) - { - BroadcastShowUi(_nearestInteractable, 0f); - } } - private IInteractable GetNearestInteractable() + protected IInteractable GetNearestInteractable() { - int nearColliderCount = Physics.OverlapSphereNonAlloc(transform.position, _restaurantPlayerDataSo.InteractionRadius, - _nearColliders, _restaurantPlayerDataSo.InteractionLayerMask, QueryTriggerInteraction.Collide); + int nearColliderCount = Physics.OverlapSphereNonAlloc(transform.position, _interactionRadius, + _nearColliders, _interactionLayerMask, QueryTriggerInteraction.Collide); - IInteractable nearestInteractable = null; - float minDistance = float.MaxValue; + IInteractable nearest = null; + float minSqrDistance = 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; + if (interactable == null || !interactable.CanInteract()) continue; + + float sqrDistance = (interactable.GetInteractableGameObject().transform.position - transform.position).sqrMagnitude; + if (sqrDistance < minSqrDistance) + { + minSqrDistance = sqrDistance; + nearest = interactable; + } } - - return nearestInteractable; - } - - private void BroadcastShowUi(IInteractable interactable, float ratio) - { - var evt = GameEvents.ShowInteractionUiEvent; - evt.TextKey = interactable.GetInteractionMessageKey(); - evt.HoldProgress = ratio; - EventBus.Broadcast(evt); + + return nearest; } + + public virtual void Invoke(RestaurantInteractionEvent evt) { } + + public GameObject GetInteractorGameObject() => gameObject; } -} \ No newline at end of file +} diff --git a/Assets/_DDD/_Scripts/RestaurantCharacter/RestaurantPlayerInteraction.cs b/Assets/_DDD/_Scripts/RestaurantCharacter/RestaurantPlayerInteraction.cs new file mode 100644 index 000000000..aa886d0dd --- /dev/null +++ b/Assets/_DDD/_Scripts/RestaurantCharacter/RestaurantPlayerInteraction.cs @@ -0,0 +1,105 @@ +using System.Threading.Tasks; +using UnityEngine; +using UnityEngine.InputSystem; + +namespace DDD +{ + public class RestaurantPlayerInteraction : RestaurantCharacterInteraction + { + private RestaurantPlayerDataSo _restaurantPlayerDataSo; + + protected override void Start() + { + base.Start(); + + _ = Initialize(); + } + + 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; + + _interactionRadius = _restaurantPlayerDataSo.InteractionRadius; + _interactionLayerMask = _restaurantPlayerDataSo.InteractionLayerMask; + + EventBus.Register(this); + } + + protected override void OnDestroy() + { + base.OnDestroy(); + + if (_restaurantPlayerDataSo != null) + { + _restaurantPlayerDataSo.InteractAction.performed -= OnInteractPerformed; + _restaurantPlayerDataSo.InteractAction.canceled -= OnInteractCanceled; + } + + EventBus.Unregister(this); + } + + private void OnInteractPerformed(InputAction.CallbackContext context) + { + if (_nearestInteractable == null || !_nearestInteractable.CanInteract()) return; + + float requiredHoldTime = _nearestInteractable.GetRequiredHoldTime(); + + if (requiredHoldTime <= 0f) + { + _nearestInteractable.OnInteracted(this); + } + else + { + _isInteracting = true; + _interactHeldTime = 0f; + _interactingTarget = _nearestInteractable; + } + } + + private void OnInteractCanceled(InputAction.CallbackContext context) + { + ResetInteractionState(); + } + + protected override void OnNearestInteractableChanged(IInteractable newTarget) + { + if (newTarget != null && newTarget.CanInteract()) + { + BroadcastShowUi(newTarget, 0f); + } + else + { + if (_isInteracting == false) + { + EventBus.Broadcast(GameEvents.HideInteractionUiEvent); + } + } + } + + protected override void OnInteractionHoldProgress(float ratio) + { + if (_interactingTarget != null) + { + BroadcastShowUi(_interactingTarget, ratio); + } + } + + protected override void OnInteractionCompleted() + { + + } + + private void BroadcastShowUi(IInteractable interactable, float ratio) + { + var evt = GameEvents.ShowInteractionUiEvent; + evt.TextKey = interactable.GetInteractionMessageKey(); + evt.HoldProgress = ratio; + EventBus.Broadcast(evt); + } + } +} \ No newline at end of file