using UnityEngine; using UnityEngine.Events; using UnityEngine.InputSystem; [RequireComponent(typeof(Collider))] public class WallInteractButton : MonoBehaviour { [Header("Interaction")] [Tooltip("Key the player must press to interact (keyboard fallback).")] [SerializeField] private Key interactKey = Key.E; [Tooltip("If true, the button can only be triggered once.")] [SerializeField] private bool oneShot = false; [Header("Physical Press")] [Tooltip("Transform that moves to simulate a physical press (optional).")] [SerializeField] private Transform buttonMesh; [Tooltip("How far the button moves when pressed.")] [SerializeField] private float pressDepth = 0.05f; [Tooltip("Speed of the press/release animation.")] [SerializeField] private float pressSpeed = 10f; [Header("Events")] public UnityEvent OnInteract; private bool m_playerInRange; private bool m_used; private Vector3 m_buttonRestPos; private Vector3 m_buttonPressedPos; private bool m_isVisuallyPressed; private void Reset() { Collider col = GetComponent(); col.isTrigger = true; } private void Start() { if (buttonMesh != null) { m_buttonRestPos = buttonMesh.localPosition; m_buttonPressedPos = m_buttonRestPos - buttonMesh.localRotation * Vector3.forward * pressDepth; } } private void Update() { if (m_playerInRange && Keyboard.current != null && Keyboard.current[interactKey].wasPressedThisFrame) { TryInteract(); } AnimateButton(); } private void TryInteract() { if (oneShot && m_used) return; m_used = true; m_isVisuallyPressed = true; OnInteract?.Invoke(); if (!oneShot) Invoke(nameof(ReleaseVisual), 0.15f); } private void ReleaseVisual() { m_isVisuallyPressed = false; } private void AnimateButton() { if (buttonMesh == null) return; Vector3 target = m_isVisuallyPressed ? m_buttonPressedPos : m_buttonRestPos; buttonMesh.localPosition = Vector3.Lerp(buttonMesh.localPosition, target, Time.deltaTime * pressSpeed); } private void OnTriggerEnter(Collider other) { if (IsPlayer(other)) m_playerInRange = true; } private void OnTriggerExit(Collider other) { if (IsPlayer(other)) m_playerInRange = false; } private bool IsPlayer(Collider other) { if (other.CompareTag("Player")) return true; if (other.GetComponentInParent() != null) return true; return false; } #if UNITY_EDITOR private void OnDrawGizmos() { Collider col = GetComponent(); if (col == null) return; Gizmos.matrix = transform.localToWorldMatrix; Gizmos.color = m_playerInRange ? new Color(0f, 1f, 0f, 0.25f) : new Color(1f, 0.9f, 0f, 0.15f); if (col is SphereCollider sphere) { Gizmos.DrawSphere(sphere.center, sphere.radius); Gizmos.color = m_playerInRange ? Color.green : Color.yellow; Gizmos.DrawWireSphere(sphere.center, sphere.radius); } else if (col is BoxCollider box) { Gizmos.DrawCube(box.center, box.size); Gizmos.color = m_playerInRange ? Color.green : Color.yellow; Gizmos.DrawWireCube(box.center, box.size); } } #endif }