122 lines
4.4 KiB
C#
122 lines
4.4 KiB
C#
using System.Threading.Tasks;
|
|
using Sirenix.OdinInspector;
|
|
using UnityEngine;
|
|
using UnityEngine.InputSystem;
|
|
|
|
namespace DDD
|
|
{
|
|
public class RestaurantCharacterInteraction : MonoBehaviour, IInteractor, IEventHandler<RestaurantInteractionEvent>
|
|
{
|
|
private RestaurantPlayerDataSo _restaurantPlayerDataSo;
|
|
|
|
[ReadOnly, SerializeField] private Collider[] _nearColliders = new Collider[10];
|
|
private IInteractable _nearestInteractable;
|
|
|
|
private float _interactHeldTime;
|
|
private bool _isInteracting;
|
|
|
|
private void Start()
|
|
{
|
|
_ = 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<RestaurantInteractionEvent>(this);
|
|
|
|
if (_restaurantPlayerDataSo)
|
|
{
|
|
_restaurantPlayerDataSo.InteractAction.performed -= OnInteractPerformed;
|
|
_restaurantPlayerDataSo.InteractAction.canceled -= OnInteractCanceled;
|
|
}
|
|
}
|
|
|
|
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;
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
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<IInteractable>();
|
|
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;
|
|
}
|
|
}
|
|
} |