Files
FablishRPG/Assets/Scripts/InteractionController.cs

101 lines
3.5 KiB
C#

using UnityEngine;
using UnityEngine.InputSystem;
public class InteractionController : MonoBehaviour
{
[Header("Interaction Settings")]
[Tooltip("How large the proximity bubble is around the player (e.g. 3 meters).")]
public float interactionDistance = 3f;
[Tooltip("Layers that contain interactable objects (e.g. NPC, Default)")]
public LayerMask interactableLayers;
[Header("References")]
public PlayerUIManager uiManager;
[Header("Input")]
[Tooltip("The key used to interact")]
public Key interactKey = Key.E;
// We store whatever we are currently closest to
private IInteractable _currentInteractable;
private void Update()
{
if (uiManager == null) return;
// Create a sphere around the player to find all interactables in range
// Use QueryTriggerInteraction.Ignore so we don't accidentally interact with giant invisible AI/Aggro triggers!
Collider[] hits = Physics.OverlapSphere(transform.position, interactionDistance, interactableLayers, QueryTriggerInteraction.Ignore);
IInteractable closestInteractable = null;
float closestDistance = float.MaxValue;
// Loop through everything in our bubble to find the closest one
foreach (var hit in hits)
{
// Ignore our own body
if (hit.transform.root == transform.root) continue;
IInteractable interactable = hit.GetComponentInParent<IInteractable>();
if (interactable != null && interactable.CanInteract())
{
float dist = Vector3.Distance(transform.position, hit.ClosestPoint(transform.position));
if (dist < closestDistance)
{
closestDistance = dist;
closestInteractable = interactable;
}
}
}
// If we found something valid nearby
if (closestInteractable != null)
{
if (_currentInteractable != closestInteractable)
{
_currentInteractable = closestInteractable;
ShowPrompt(closestInteractable.GetInteractText(), closestInteractable.GetSecondaryInteractText());
}
// Listen for input
if (Keyboard.current != null && Keyboard.current[interactKey].wasPressedThisFrame)
{
closestInteractable.Interact(gameObject);
}
}
else
{
// Nothing in range, or closest thing can't be interacted with anymore
if (_currentInteractable != null)
{
_currentInteractable = null;
HidePrompt();
}
}
}
private void ShowPrompt(string actionText, string secondaryText)
{
if (uiManager.interactionPanel != null) uiManager.interactionPanel.SetActive(true);
if (uiManager.interactionText != null) uiManager.interactionText.text = actionText;
if (uiManager.interactionSecondaryText != null)
{
uiManager.interactionSecondaryText.text = secondaryText;
}
}
private void HidePrompt()
{
if (uiManager.interactionPanel != null) uiManager.interactionPanel.SetActive(false);
}
// Draws a helpful visual bubble in the Scene view so you can see your interaction range!
private void OnDrawGizmosSelected()
{
Gizmos.color = new Color(0f, 1f, 0f, 0.3f);
Gizmos.DrawSphere(transform.position, interactionDistance);
}
}