DDD-65 상호작용 Ui 구성

This commit is contained in:
NTG_Lenovo 2025-08-05 19:46:36 +09:00
parent 7139791aac
commit 39db7e245f
5 changed files with 131 additions and 7 deletions

View File

@ -11,6 +11,8 @@ public static class GameEvents
public static OpenPopupUiEvent OpenPopupUiEvent = new(); public static OpenPopupUiEvent OpenPopupUiEvent = new();
public static ClosePopupUiEvent ClosePopupUiEvent = new(); public static ClosePopupUiEvent ClosePopupUiEvent = new();
public static ShowGlobalMessageEvent ShowGlobalMessageEvent = new(); public static ShowGlobalMessageEvent ShowGlobalMessageEvent = new();
public static ShowInteractionUiEvent ShowInteractionUiEvent = new();
public static HideInteractionUiEvent HideInteractionUiEvent = new();
public static InventoryChangedEvent InventoryChangedEvent = new(); public static InventoryChangedEvent InventoryChangedEvent = new();
} }
@ -76,6 +78,14 @@ public class InventoryChangedEvent : IEvent
public string ItemId; public string ItemId;
public int NewCount; public int NewCount;
} }
public class ShowInteractionUiEvent : IEvent
{
public string TextKey;
public float HoldProgress;
}
public class HideInteractionUiEvent : IEvent { }
#region RestaurantInteractionEvents #region RestaurantInteractionEvents

View File

@ -16,6 +16,7 @@ public interface IInteractable
GameObject GetInteractableGameObject(); GameObject GetInteractableGameObject();
void InitializeInteraction(InteractionType interactionType); void InitializeInteraction(InteractionType interactionType);
float GetRequiredHoldTime(); float GetRequiredHoldTime();
string GetInteractionMessageKey();
} }
public interface IInteractor public interface IInteractor
{ {

View File

@ -0,0 +1,54 @@
using UnityEngine;
using UnityEngine.Localization;
using UnityEngine.Localization.Components;
using UnityEngine.UI;
namespace DDD
{
public class InteractionMessageUi : BaseUi, IEventHandler<ShowInteractionUiEvent>, IEventHandler<HideInteractionUiEvent>
{
[SerializeField] private Image _filledImage;
[SerializeField] private LocalizeStringEvent _textLabelLocalizeStringEvent;
private LocalizedString _previousLocalizedString;
protected override void Start()
{
base.Start();
_filledImage.fillAmount = 0f;
EventBus.Register<ShowInteractionUiEvent>(this);
EventBus.Register<HideInteractionUiEvent>(this);
}
protected override void OnDestroy()
{
base.OnDestroy();
EventBus.Unregister<ShowInteractionUiEvent>(this);
EventBus.Unregister<HideInteractionUiEvent>(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();
}
}
}

View File

@ -11,6 +11,8 @@ public class RestaurantCharacterInteraction : MonoBehaviour, IInteractor, IEvent
[ReadOnly, SerializeField] private Collider[] _nearColliders = new Collider[10]; [ReadOnly, SerializeField] private Collider[] _nearColliders = new Collider[10];
private IInteractable _nearestInteractable; private IInteractable _nearestInteractable;
private IInteractable _previousInteractable;
private IInteractable _interactingTarget;
private float _interactHeldTime; private float _interactHeldTime;
private bool _isInteracting; private bool _isInteracting;
@ -25,16 +27,53 @@ private void Update()
if (!_restaurantPlayerDataSo) return; if (!_restaurantPlayerDataSo) return;
_nearestInteractable = GetNearestInteractable(); _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; _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; _isInteracting = true;
_interactHeldTime = 0f; _interactHeldTime = 0f;
_interactingTarget = _nearestInteractable;
} }
} }
@ -93,6 +133,12 @@ private void OnInteractCanceled(InputAction.CallbackContext context)
{ {
_isInteracting = false; _isInteracting = false;
_interactHeldTime = 0f; _interactHeldTime = 0f;
_interactingTarget = null;
if (_nearestInteractable != null && _nearestInteractable.CanInteract())
{
BroadcastShowUi(_nearestInteractable, 0f);
}
} }
private IInteractable GetNearestInteractable() private IInteractable GetNearestInteractable()
@ -115,8 +161,15 @@ private IInteractable GetNearestInteractable()
minDistance = sqrMagnitude; minDistance = sqrMagnitude;
} }
print(nearestInteractable?.GetInteractableGameObject().name);
return nearestInteractable; return nearestInteractable;
} }
private void BroadcastShowUi(IInteractable interactable, float ratio)
{
var evt = GameEvents.ShowInteractionUiEvent;
evt.TextKey = interactable.GetInteractionMessageKey();
evt.HoldProgress = ratio;
EventBus.Broadcast(evt);
}
} }
} }

View File

@ -6,6 +6,7 @@ public class RestaurantInteractionComponent : MonoBehaviour, IInteractable
{ {
[SerializeField] private InteractionType _interactionType = InteractionType.None; [SerializeField] private InteractionType _interactionType = InteractionType.None;
[SerializeField] private float _holdTime = 1f; [SerializeField] private float _holdTime = 1f;
[SerializeField] private string _interactionMessageKey = "";
public bool CanInteract() public bool CanInteract()
{ {
@ -42,5 +43,10 @@ public float GetRequiredHoldTime()
{ {
return _holdTime; return _holdTime;
} }
public string GetInteractionMessageKey()
{
return _interactionMessageKey;
}
} }
} }