상호작용 클래스 분리
This commit is contained in:
parent
0b34f02a34
commit
239ab0601a
@ -1,62 +1,39 @@
|
|||||||
using System.Threading.Tasks;
|
|
||||||
using Sirenix.OdinInspector;
|
using Sirenix.OdinInspector;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.InputSystem;
|
|
||||||
|
|
||||||
namespace DDD
|
namespace DDD
|
||||||
{
|
{
|
||||||
public class RestaurantCharacterInteraction : MonoBehaviour, IInteractor, IEventHandler<RestaurantInteractionEvent>
|
public class RestaurantCharacterInteraction : MonoBehaviour, IInteractor, IEventHandler<RestaurantInteractionEvent>
|
||||||
{
|
{
|
||||||
private RestaurantPlayerDataSo _restaurantPlayerDataSo;
|
[SerializeField, ReadOnly] protected Collider[] _nearColliders = new Collider[10];
|
||||||
|
|
||||||
[ReadOnly, SerializeField] private Collider[] _nearColliders = new Collider[10];
|
protected IInteractable _nearestInteractable;
|
||||||
private IInteractable _nearestInteractable;
|
protected IInteractable _previousInteractable;
|
||||||
private IInteractable _previousInteractable;
|
protected IInteractable _interactingTarget;
|
||||||
private IInteractable _interactingTarget;
|
|
||||||
|
|
||||||
private float _interactHeldTime;
|
protected float _interactHeldTime;
|
||||||
private bool _isInteracting;
|
protected bool _isInteracting;
|
||||||
|
|
||||||
private void Start()
|
protected float _interactionRadius = 1f;
|
||||||
|
protected LayerMask _interactionLayerMask = (LayerMask)(-1);
|
||||||
|
|
||||||
|
protected virtual void Start() { }
|
||||||
|
|
||||||
|
protected virtual void Update()
|
||||||
{
|
{
|
||||||
_ = Initialize();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Update()
|
|
||||||
{
|
|
||||||
if (!_restaurantPlayerDataSo) return;
|
|
||||||
|
|
||||||
_nearestInteractable = GetNearestInteractable();
|
_nearestInteractable = GetNearestInteractable();
|
||||||
|
|
||||||
if (_nearestInteractable != _previousInteractable)
|
if (_nearestInteractable != _previousInteractable)
|
||||||
{
|
{
|
||||||
_previousInteractable = _nearestInteractable;
|
_previousInteractable = _nearestInteractable;
|
||||||
|
OnNearestInteractableChanged(_nearestInteractable);
|
||||||
if (_nearestInteractable != null && _nearestInteractable.CanInteract())
|
|
||||||
{
|
|
||||||
BroadcastShowUi(_nearestInteractable, 0f);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
EventBus.Broadcast(GameEvents.HideInteractionUiEvent);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_isInteracting)
|
if (_isInteracting)
|
||||||
{
|
{
|
||||||
// 도중에 타겟이 바뀐 경우 초기화
|
|
||||||
if (_nearestInteractable != _interactingTarget)
|
if (_nearestInteractable != _interactingTarget)
|
||||||
{
|
{
|
||||||
_isInteracting = false;
|
ResetInteractionState();
|
||||||
_interactHeldTime = 0f;
|
|
||||||
_interactingTarget = null;
|
|
||||||
|
|
||||||
// UI 초기화
|
|
||||||
if (_nearestInteractable != null && _nearestInteractable.CanInteract())
|
|
||||||
{
|
|
||||||
BroadcastShowUi(_nearestInteractable, 0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,109 +44,56 @@ private void Update()
|
|||||||
|
|
||||||
if (_interactHeldTime >= requiredHoldTime)
|
if (_interactHeldTime >= requiredHoldTime)
|
||||||
{
|
{
|
||||||
ratio = 0f;
|
|
||||||
_isInteracting = false;
|
_isInteracting = false;
|
||||||
_interactingTarget.OnInteracted(this);
|
_interactingTarget.OnInteracted(this);
|
||||||
_interactingTarget = null;
|
_interactingTarget = null;
|
||||||
|
OnInteractionCompleted();
|
||||||
}
|
}
|
||||||
|
|
||||||
BroadcastShowUi(_interactingTarget, ratio);
|
OnInteractionHoldProgress(ratio);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnDestroy()
|
protected virtual void OnDestroy() { }
|
||||||
{
|
|
||||||
EventBus.Unregister<RestaurantInteractionEvent>(this);
|
|
||||||
|
|
||||||
if (_restaurantPlayerDataSo)
|
protected virtual void OnNearestInteractableChanged(IInteractable newTarget) { }
|
||||||
{
|
protected virtual void OnInteractionHoldProgress(float ratio) { }
|
||||||
_restaurantPlayerDataSo.InteractAction.performed -= OnInteractPerformed;
|
protected virtual void OnInteractionCompleted() { }
|
||||||
_restaurantPlayerDataSo.InteractAction.canceled -= OnInteractCanceled;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task Initialize()
|
protected void ResetInteractionState()
|
||||||
{
|
|
||||||
_restaurantPlayerDataSo = await AssetManager.LoadAsset<RestaurantPlayerDataSo>(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<RestaurantInteractionEvent>(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)
|
|
||||||
{
|
{
|
||||||
_isInteracting = false;
|
_isInteracting = false;
|
||||||
_interactHeldTime = 0f;
|
_interactHeldTime = 0f;
|
||||||
|
OnInteractionHoldProgress(0f);
|
||||||
_interactingTarget = null;
|
_interactingTarget = null;
|
||||||
|
|
||||||
if (_nearestInteractable != null && _nearestInteractable.CanInteract())
|
|
||||||
{
|
|
||||||
BroadcastShowUi(_nearestInteractable, 0f);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private IInteractable GetNearestInteractable()
|
protected IInteractable GetNearestInteractable()
|
||||||
{
|
{
|
||||||
int nearColliderCount = Physics.OverlapSphereNonAlloc(transform.position, _restaurantPlayerDataSo.InteractionRadius,
|
int nearColliderCount = Physics.OverlapSphereNonAlloc(transform.position, _interactionRadius,
|
||||||
_nearColliders, _restaurantPlayerDataSo.InteractionLayerMask, QueryTriggerInteraction.Collide);
|
_nearColliders, _interactionLayerMask, QueryTriggerInteraction.Collide);
|
||||||
|
|
||||||
IInteractable nearestInteractable = null;
|
IInteractable nearest = null;
|
||||||
float minDistance = float.MaxValue;
|
float minSqrDistance = float.MaxValue;
|
||||||
|
|
||||||
for (int i = 0; i < nearColliderCount; i++)
|
for (int i = 0; i < nearColliderCount; i++)
|
||||||
{
|
{
|
||||||
var interactable = _nearColliders[i].GetComponent<IInteractable>();
|
var interactable = _nearColliders[i].GetComponent<IInteractable>();
|
||||||
if (interactable == null || interactable.CanInteract() == false) continue;
|
if (interactable == null || !interactable.CanInteract()) continue;
|
||||||
|
|
||||||
float sqrMagnitude = (interactable.GetInteractableGameObject().transform.position - transform.position).sqrMagnitude;
|
float sqrDistance = (interactable.GetInteractableGameObject().transform.position - transform.position).sqrMagnitude;
|
||||||
if (sqrMagnitude > minDistance) continue;
|
if (sqrDistance < minSqrDistance)
|
||||||
|
|
||||||
nearestInteractable = interactable;
|
|
||||||
minDistance = sqrMagnitude;
|
|
||||||
}
|
|
||||||
|
|
||||||
return nearestInteractable;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void BroadcastShowUi(IInteractable interactable, float ratio)
|
|
||||||
{
|
{
|
||||||
var evt = GameEvents.ShowInteractionUiEvent;
|
minSqrDistance = sqrDistance;
|
||||||
evt.TextKey = interactable.GetInteractionMessageKey();
|
nearest = interactable;
|
||||||
evt.HoldProgress = ratio;
|
|
||||||
EventBus.Broadcast(evt);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nearest;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Invoke(RestaurantInteractionEvent evt) { }
|
||||||
|
|
||||||
|
public GameObject GetInteractorGameObject() => gameObject;
|
||||||
|
}
|
||||||
}
|
}
|
@ -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<RestaurantPlayerDataSo>(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<RestaurantInteractionEvent>(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnDestroy()
|
||||||
|
{
|
||||||
|
base.OnDestroy();
|
||||||
|
|
||||||
|
if (_restaurantPlayerDataSo != null)
|
||||||
|
{
|
||||||
|
_restaurantPlayerDataSo.InteractAction.performed -= OnInteractPerformed;
|
||||||
|
_restaurantPlayerDataSo.InteractAction.canceled -= OnInteractCanceled;
|
||||||
|
}
|
||||||
|
|
||||||
|
EventBus.Unregister<RestaurantInteractionEvent>(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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user