2025-08-28 03:43:32 +00:00
|
|
|
using System;
|
|
|
|
using System.Collections.Generic;
|
2025-08-06 08:43:41 +00:00
|
|
|
using System.Threading.Tasks;
|
|
|
|
using UnityEngine;
|
|
|
|
using UnityEngine.InputSystem;
|
|
|
|
|
2025-08-27 07:52:34 +00:00
|
|
|
namespace DDD.Restaurant
|
2025-08-06 08:43:41 +00:00
|
|
|
{
|
2025-08-27 08:25:11 +00:00
|
|
|
public class PlayerInteraction : CharacterInteraction
|
2025-08-06 08:43:41 +00:00
|
|
|
{
|
2025-08-18 10:48:36 +00:00
|
|
|
private RestaurantPlayerData _restaurantPlayerDataSo;
|
2025-08-06 08:43:41 +00:00
|
|
|
|
2025-08-27 07:52:34 +00:00
|
|
|
private float _interactHeldTime;
|
|
|
|
private bool _isInteracting;
|
|
|
|
|
2025-08-06 08:43:41 +00:00
|
|
|
protected override void Start()
|
|
|
|
{
|
|
|
|
base.Start();
|
|
|
|
|
|
|
|
_ = Initialize();
|
|
|
|
}
|
|
|
|
|
2025-08-14 11:59:40 +00:00
|
|
|
private Task Initialize()
|
2025-08-06 08:43:41 +00:00
|
|
|
{
|
2025-08-19 04:51:42 +00:00
|
|
|
_restaurantPlayerDataSo = RestaurantData.Instance.PlayerData;
|
2025-08-06 08:43:41 +00:00
|
|
|
Debug.Assert(_restaurantPlayerDataSo != null, "_restaurantPlayerDataSo is null");
|
|
|
|
|
2025-08-13 09:31:34 +00:00
|
|
|
_restaurantPlayerDataSo!.InteractAction = InputManager.Instance.GetAction(InputActionMaps.Restaurant, nameof(RestaurantActions.Interact));
|
2025-08-06 08:43:41 +00:00
|
|
|
_restaurantPlayerDataSo.InteractAction.performed += OnInteractPerformed;
|
|
|
|
_restaurantPlayerDataSo.InteractAction.canceled += OnInteractCanceled;
|
|
|
|
|
|
|
|
_interactionRadius = _restaurantPlayerDataSo.InteractionRadius;
|
|
|
|
_interactionLayerMask = _restaurantPlayerDataSo.InteractionLayerMask;
|
|
|
|
|
|
|
|
EventBus.Register<RestaurantInteractionEvent>(this);
|
2025-08-14 11:59:40 +00:00
|
|
|
|
|
|
|
return Task.CompletedTask;
|
2025-08-06 08:43:41 +00:00
|
|
|
}
|
|
|
|
|
2025-08-28 03:43:32 +00:00
|
|
|
public override void InitializeSolvers()
|
|
|
|
{
|
|
|
|
var typesToSolver = RestaurantInteractionEventSolvers.TypeToSolver;
|
|
|
|
var playerSolver = RestaurantInteractionEventSolvers.TypeToPlayerSolver;
|
|
|
|
foreach(var pair in playerSolver)
|
|
|
|
{
|
|
|
|
typesToSolver.Remove(pair.Key);
|
|
|
|
}
|
|
|
|
InitializeInteractionSolvers(typesToSolver);
|
|
|
|
InitializeInteractionSolvers(playerSolver);
|
|
|
|
}
|
|
|
|
|
2025-08-06 08:43:41 +00:00
|
|
|
protected override void OnDestroy()
|
|
|
|
{
|
|
|
|
base.OnDestroy();
|
|
|
|
|
|
|
|
if (_restaurantPlayerDataSo != null)
|
|
|
|
{
|
|
|
|
_restaurantPlayerDataSo.InteractAction.performed -= OnInteractPerformed;
|
|
|
|
_restaurantPlayerDataSo.InteractAction.canceled -= OnInteractCanceled;
|
|
|
|
}
|
|
|
|
|
|
|
|
EventBus.Unregister<RestaurantInteractionEvent>(this);
|
|
|
|
}
|
2025-08-27 07:52:34 +00:00
|
|
|
|
|
|
|
protected virtual void Update()
|
|
|
|
{
|
|
|
|
_nearestInteractable = GetNearestInteractable();
|
|
|
|
|
|
|
|
if (_nearestInteractable != _previousInteractable)
|
|
|
|
{
|
|
|
|
_previousInteractable = _nearestInteractable;
|
|
|
|
OnNearestInteractableChanged(_nearestInteractable);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_isInteracting)
|
|
|
|
{
|
|
|
|
if (_nearestInteractable != _interactingTarget || CanInteractTo(_interactingTarget) == false)
|
|
|
|
{
|
|
|
|
ResetInteractionState();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
_interactHeldTime += Time.deltaTime;
|
|
|
|
|
|
|
|
float requiredHoldTime = _interactingTarget.GetExecutionParameters().HoldTime;
|
|
|
|
float ratio = Mathf.Clamp01(_interactHeldTime / requiredHoldTime);
|
2025-08-27 08:05:54 +00:00
|
|
|
|
2025-08-27 07:52:34 +00:00
|
|
|
if (_interactHeldTime >= requiredHoldTime)
|
|
|
|
{
|
2025-08-27 08:05:54 +00:00
|
|
|
TryInteraction(_nearestInteractable);
|
|
|
|
OnInteractionCompleted();
|
2025-08-27 07:52:34 +00:00
|
|
|
|
|
|
|
ResetInteractionState();
|
2025-08-27 08:05:54 +00:00
|
|
|
OnInteractionHoldProgress(0f);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
OnInteractionHoldProgress(ratio);
|
2025-08-27 07:52:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-08-06 08:43:41 +00:00
|
|
|
|
|
|
|
private void OnInteractPerformed(InputAction.CallbackContext context)
|
|
|
|
{
|
2025-08-14 04:46:36 +00:00
|
|
|
if (_nearestInteractable == null || CanInteractTo(_nearestInteractable) == false) return;
|
2025-08-06 08:43:41 +00:00
|
|
|
|
2025-08-20 05:07:33 +00:00
|
|
|
float requiredHoldTime = _nearestInteractable.GetExecutionParameters().HoldTime;
|
2025-08-06 08:43:41 +00:00
|
|
|
|
|
|
|
if (requiredHoldTime <= 0f)
|
|
|
|
{
|
2025-08-27 08:05:54 +00:00
|
|
|
TryInteraction(_nearestInteractable);
|
2025-08-06 08:43:41 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
_isInteracting = true;
|
|
|
|
_interactHeldTime = 0f;
|
|
|
|
_interactingTarget = _nearestInteractable;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void OnInteractCanceled(InputAction.CallbackContext context)
|
|
|
|
{
|
2025-08-07 08:51:36 +00:00
|
|
|
OnInteractionHoldProgress(0f);
|
2025-08-06 08:43:41 +00:00
|
|
|
ResetInteractionState();
|
|
|
|
}
|
|
|
|
|
2025-08-27 07:52:34 +00:00
|
|
|
protected void OnNearestInteractableChanged(IInteractable newTarget)
|
2025-08-06 08:43:41 +00:00
|
|
|
{
|
2025-08-13 09:31:34 +00:00
|
|
|
if (newTarget != null)
|
2025-08-06 08:43:41 +00:00
|
|
|
{
|
2025-08-14 04:46:36 +00:00
|
|
|
BroadcastShowUi(newTarget, CanInteractTo(newTarget), 0f);
|
2025-08-06 08:43:41 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2025-08-07 08:51:36 +00:00
|
|
|
EventBus.Broadcast(GameEvents.HideInteractionUiEvent);
|
2025-08-06 08:43:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-08-27 07:52:34 +00:00
|
|
|
protected void OnInteractionHoldProgress(float ratio)
|
2025-08-06 08:43:41 +00:00
|
|
|
{
|
|
|
|
if (_interactingTarget != null)
|
|
|
|
{
|
2025-08-14 04:46:36 +00:00
|
|
|
BroadcastShowUi(_interactingTarget, CanInteractTo(_interactingTarget), ratio);
|
2025-08-06 08:43:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected override void OnInteractionCompleted()
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2025-08-13 09:31:34 +00:00
|
|
|
private void BroadcastShowUi(IInteractable interactable, bool canInteract, float ratio)
|
2025-08-06 08:43:41 +00:00
|
|
|
{
|
|
|
|
var evt = GameEvents.ShowInteractionUiEvent;
|
2025-08-13 09:31:34 +00:00
|
|
|
evt.CanInteract = canInteract;
|
2025-08-20 05:07:33 +00:00
|
|
|
evt.TextKey = interactable.GetDisplayParameters().MessageKey;
|
2025-08-06 08:43:41 +00:00
|
|
|
evt.HoldProgress = ratio;
|
|
|
|
EventBus.Broadcast(evt);
|
|
|
|
}
|
2025-08-27 07:52:34 +00:00
|
|
|
|
|
|
|
protected void ResetInteractionState()
|
|
|
|
{
|
|
|
|
_interactingTarget = null;
|
|
|
|
|
|
|
|
// Hold Progress
|
|
|
|
_isInteracting = false;
|
|
|
|
_interactingTarget = null;
|
|
|
|
_interactHeldTime = 0f;
|
|
|
|
OnInteractionHoldProgress(0f);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected IInteractable GetNearestInteractable()
|
|
|
|
{
|
|
|
|
int colliderCount = Physics.OverlapSphereNonAlloc(transform.position, _interactionRadius, _nearColliders, _interactionLayerMask, QueryTriggerInteraction.Collide);
|
|
|
|
float closestDistance = float.MaxValue;
|
|
|
|
IInteractable closest = null;
|
|
|
|
|
|
|
|
for (int i = 0; i < colliderCount; i++)
|
|
|
|
{
|
|
|
|
var col = _nearColliders[i];
|
|
|
|
if (col.TryGetComponent<IInteractable>(out var interactable) == false) continue;
|
|
|
|
|
|
|
|
var type = interactable.GetInteractionType();
|
|
|
|
if (interactable.IsInteractionHidden()) continue;
|
|
|
|
if (CanSolveInteractionType(type) == false) continue;
|
|
|
|
|
|
|
|
float distance = Vector3.Distance(transform.position, col.transform.position);
|
|
|
|
if (distance < closestDistance)
|
|
|
|
{
|
|
|
|
closestDistance = distance;
|
|
|
|
closest = interactable;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return closest;
|
|
|
|
}
|
2025-08-06 08:43:41 +00:00
|
|
|
}
|
|
|
|
}
|