106 lines
3.1 KiB
C#
106 lines
3.1 KiB
C#
using OTGIntegrated.UI;
|
|
using UnityEngine;
|
|
|
|
namespace OTGIntegrated.Player
|
|
{
|
|
public interface IInteractable
|
|
{
|
|
Transform InteractTransform { get; }
|
|
string GetPrompt();
|
|
bool CanInteract(GameObject interactor);
|
|
void Interact(GameObject interactor);
|
|
}
|
|
|
|
public sealed class PlayerInteraction : MonoBehaviour
|
|
{
|
|
[SerializeField] private float interactionRadius = 2.6f;
|
|
[SerializeField] private LayerMask interactionMask = ~0;
|
|
public InteractionPromptUI promptUI;
|
|
|
|
private readonly Collider[] hits = new Collider[24];
|
|
private PlayerController playerController;
|
|
private IInteractable currentInteractable;
|
|
|
|
private void Awake()
|
|
{
|
|
playerController = GetComponent<PlayerController>();
|
|
if (promptUI == null)
|
|
{
|
|
promptUI = FindObjectOfType<InteractionPromptUI>();
|
|
}
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
if (playerController != null && !playerController.InputEnabled)
|
|
{
|
|
SetCurrent(null);
|
|
return;
|
|
}
|
|
|
|
FindNearestInteractable();
|
|
|
|
if (currentInteractable != null && Input.GetKeyDown(KeyCode.E))
|
|
{
|
|
currentInteractable.Interact(gameObject);
|
|
}
|
|
}
|
|
|
|
private void FindNearestInteractable()
|
|
{
|
|
int count = Physics.OverlapSphereNonAlloc(transform.position, interactionRadius, hits, interactionMask, QueryTriggerInteraction.Collide);
|
|
IInteractable nearest = null;
|
|
float nearestDistance = float.MaxValue;
|
|
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
Collider hit = hits[i];
|
|
if (hit == null)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
IInteractable interactable = hit.GetComponentInParent<IInteractable>();
|
|
if (interactable == null || !interactable.CanInteract(gameObject))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
Transform interactTransform = interactable.InteractTransform != null ? interactable.InteractTransform : hit.transform;
|
|
float distance = (interactTransform.position - transform.position).sqrMagnitude;
|
|
if (distance < nearestDistance)
|
|
{
|
|
nearestDistance = distance;
|
|
nearest = interactable;
|
|
}
|
|
}
|
|
|
|
SetCurrent(nearest);
|
|
}
|
|
|
|
private void SetCurrent(IInteractable interactable)
|
|
{
|
|
currentInteractable = interactable;
|
|
if (promptUI == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (currentInteractable == null)
|
|
{
|
|
promptUI.Hide();
|
|
}
|
|
else
|
|
{
|
|
promptUI.Show(currentInteractable.GetPrompt());
|
|
}
|
|
}
|
|
|
|
private void OnDrawGizmosSelected()
|
|
{
|
|
Gizmos.color = new Color(1f, 0.75f, 0.2f, 0.25f);
|
|
Gizmos.DrawSphere(transform.position, interactionRadius);
|
|
}
|
|
}
|
|
}
|