From 39db7e245f81da794033c08f675863d4c2757891 Mon Sep 17 00:00:00 2001 From: NTG_Lenovo Date: Tue, 5 Aug 2025 19:46:36 +0900 Subject: [PATCH] =?UTF-8?q?DDD-65=20=EC=83=81=ED=98=B8=EC=9E=91=EC=9A=A9?= =?UTF-8?q?=20Ui=20=EA=B5=AC=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Assets/_DDD/_Scripts/GameEvent/GameEvents.cs | 10 +++ .../_DDD/_Scripts/GameEvent/IInteractable.cs | 1 + .../_Scripts/GameUi/InteractionMessageUi.cs | 54 +++++++++++++++ .../RestaurantCharacterInteraction.cs | 67 +++++++++++++++++-- .../RestaurantInteractionComponent.cs | 6 ++ 5 files changed, 131 insertions(+), 7 deletions(-) create mode 100644 Assets/_DDD/_Scripts/GameUi/InteractionMessageUi.cs diff --git a/Assets/_DDD/_Scripts/GameEvent/GameEvents.cs b/Assets/_DDD/_Scripts/GameEvent/GameEvents.cs index 8de0c5e22..364e9580a 100644 --- a/Assets/_DDD/_Scripts/GameEvent/GameEvents.cs +++ b/Assets/_DDD/_Scripts/GameEvent/GameEvents.cs @@ -11,6 +11,8 @@ public static class GameEvents public static OpenPopupUiEvent OpenPopupUiEvent = new(); public static ClosePopupUiEvent ClosePopupUiEvent = new(); public static ShowGlobalMessageEvent ShowGlobalMessageEvent = new(); + public static ShowInteractionUiEvent ShowInteractionUiEvent = new(); + public static HideInteractionUiEvent HideInteractionUiEvent = new(); public static InventoryChangedEvent InventoryChangedEvent = new(); } @@ -76,6 +78,14 @@ public class InventoryChangedEvent : IEvent public string ItemId; public int NewCount; } + + public class ShowInteractionUiEvent : IEvent + { + public string TextKey; + public float HoldProgress; + } + + public class HideInteractionUiEvent : IEvent { } #region RestaurantInteractionEvents diff --git a/Assets/_DDD/_Scripts/GameEvent/IInteractable.cs b/Assets/_DDD/_Scripts/GameEvent/IInteractable.cs index 4cbcd82c8..e24b03898 100644 --- a/Assets/_DDD/_Scripts/GameEvent/IInteractable.cs +++ b/Assets/_DDD/_Scripts/GameEvent/IInteractable.cs @@ -16,6 +16,7 @@ public interface IInteractable GameObject GetInteractableGameObject(); void InitializeInteraction(InteractionType interactionType); float GetRequiredHoldTime(); + string GetInteractionMessageKey(); } public interface IInteractor { diff --git a/Assets/_DDD/_Scripts/GameUi/InteractionMessageUi.cs b/Assets/_DDD/_Scripts/GameUi/InteractionMessageUi.cs new file mode 100644 index 000000000..8777f5e46 --- /dev/null +++ b/Assets/_DDD/_Scripts/GameUi/InteractionMessageUi.cs @@ -0,0 +1,54 @@ +using UnityEngine; +using UnityEngine.Localization; +using UnityEngine.Localization.Components; +using UnityEngine.UI; + +namespace DDD +{ + public class InteractionMessageUi : BaseUi, IEventHandler, IEventHandler + { + [SerializeField] private Image _filledImage; + [SerializeField] private LocalizeStringEvent _textLabelLocalizeStringEvent; + + private LocalizedString _previousLocalizedString; + + protected override void Start() + { + base.Start(); + + _filledImage.fillAmount = 0f; + + EventBus.Register(this); + EventBus.Register(this); + } + + protected override void OnDestroy() + { + base.OnDestroy(); + + EventBus.Unregister(this); + EventBus.Unregister(this); + } + + public void Invoke(ShowInteractionUiEvent evt) + { + _previousLocalizedString = LocalizationManager.Instance.GetLocalizedString(evt.TextKey); + if (_textLabelLocalizeStringEvent.StringReference != _previousLocalizedString) + { + _textLabelLocalizeStringEvent.StringReference = _previousLocalizedString; + } + _filledImage.fillAmount = evt.HoldProgress; + + if (_panel.activeInHierarchy == false) + { + OpenPanel(); + } + } + + public void Invoke(HideInteractionUiEvent evt) + { + _filledImage.fillAmount = 0f; + ClosePanel(); + } + } +} \ No newline at end of file diff --git a/Assets/_DDD/_Scripts/RestaurantCharacter/RestaurantCharacterInteraction.cs b/Assets/_DDD/_Scripts/RestaurantCharacter/RestaurantCharacterInteraction.cs index 5f192493f..585a6316f 100644 --- a/Assets/_DDD/_Scripts/RestaurantCharacter/RestaurantCharacterInteraction.cs +++ b/Assets/_DDD/_Scripts/RestaurantCharacter/RestaurantCharacterInteraction.cs @@ -11,6 +11,8 @@ public class RestaurantCharacterInteraction : MonoBehaviour, IInteractor, IEvent [ReadOnly, SerializeField] private Collider[] _nearColliders = new Collider[10]; private IInteractable _nearestInteractable; + private IInteractable _previousInteractable; + private IInteractable _interactingTarget; private float _interactHeldTime; private bool _isInteracting; @@ -25,16 +27,53 @@ private void Update() if (!_restaurantPlayerDataSo) return; _nearestInteractable = GetNearestInteractable(); - - if (_isInteracting && _nearestInteractable != null) - { - _interactHeldTime += Time.deltaTime; - if (_interactHeldTime >= _nearestInteractable.GetRequiredHoldTime()) + if (_nearestInteractable != _previousInteractable) + { + _previousInteractable = _nearestInteractable; + + if (_nearestInteractable != null && _nearestInteractable.CanInteract()) + { + BroadcastShowUi(_nearestInteractable, 0f); + } + else + { + EventBus.Broadcast(GameEvents.HideInteractionUiEvent); + } + } + + if (_isInteracting) + { + // 도중에 타겟이 바뀐 경우 초기화 + if (_nearestInteractable != _interactingTarget) { _isInteracting = false; - _nearestInteractable.OnInteracted(this); + _interactHeldTime = 0f; + _interactingTarget = null; + + // UI 초기화 + if (_nearestInteractable != null && _nearestInteractable.CanInteract()) + { + BroadcastShowUi(_nearestInteractable, 0f); + } + + return; } + + _interactHeldTime += Time.deltaTime; + + float requiredHoldTime = _interactingTarget.GetRequiredHoldTime(); + float ratio = Mathf.Clamp01(_interactHeldTime / requiredHoldTime); + + if (_interactHeldTime >= requiredHoldTime) + { + ratio = 0f; + _isInteracting = false; + _interactingTarget.OnInteracted(this); + _interactingTarget = null; + } + + BroadcastShowUi(_interactingTarget, ratio); } } @@ -86,6 +125,7 @@ private void OnInteractPerformed(InputAction.CallbackContext context) { _isInteracting = true; _interactHeldTime = 0f; + _interactingTarget = _nearestInteractable; } } @@ -93,6 +133,12 @@ private void OnInteractCanceled(InputAction.CallbackContext context) { _isInteracting = false; _interactHeldTime = 0f; + _interactingTarget = null; + + if (_nearestInteractable != null && _nearestInteractable.CanInteract()) + { + BroadcastShowUi(_nearestInteractable, 0f); + } } private IInteractable GetNearestInteractable() @@ -115,8 +161,15 @@ private IInteractable GetNearestInteractable() minDistance = sqrMagnitude; } - print(nearestInteractable?.GetInteractableGameObject().name); return nearestInteractable; } + + 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 diff --git a/Assets/_DDD/_Scripts/RestaurantEvent/RestaurantInteractionComponent.cs b/Assets/_DDD/_Scripts/RestaurantEvent/RestaurantInteractionComponent.cs index cd9c070b7..c52e944e6 100644 --- a/Assets/_DDD/_Scripts/RestaurantEvent/RestaurantInteractionComponent.cs +++ b/Assets/_DDD/_Scripts/RestaurantEvent/RestaurantInteractionComponent.cs @@ -6,6 +6,7 @@ public class RestaurantInteractionComponent : MonoBehaviour, IInteractable { [SerializeField] private InteractionType _interactionType = InteractionType.None; [SerializeField] private float _holdTime = 1f; + [SerializeField] private string _interactionMessageKey = ""; public bool CanInteract() { @@ -42,5 +43,10 @@ public float GetRequiredHoldTime() { return _holdTime; } + + public string GetInteractionMessageKey() + { + return _interactionMessageKey; + } } } \ No newline at end of file