Files
HeadlessHazard/Assets/Code/Scripts/Interaction/PressurePlateButton.cs
2026-03-13 09:49:50 +01:00

106 lines
2.8 KiB
C#

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
[RequireComponent(typeof(Collider))]
public class PressurePlateButton : MonoBehaviour
{
[Header("Detection")]
[Tooltip("Layers that can activate the plate. Keep default to allow everything.")]
[SerializeField] private LayerMask detectionMask = ~0;
[Tooltip("If true, rigidbody objects can activate the plate.")]
[SerializeField] private bool allowRigidbodies = true;
[Tooltip("If true, the Player can activate the plate (tag Player or PlayerMovement component).")]
[SerializeField] private bool allowPlayer = true;
[Header("Events")]
public UnityEvent OnPressed;
public UnityEvent OnReleased;
private readonly HashSet<Collider> m_validCollidersOnPlate = new HashSet<Collider>();
private readonly HashSet<Collider> m_stayedThisPhysicsFrame = new HashSet<Collider>();
private bool m_isPressed;
private void Reset()
{
Collider col = GetComponent<Collider>();
col.isTrigger = true;
}
private void OnTriggerEnter(Collider other)
{
if (!IsValidActivator(other))
return;
m_validCollidersOnPlate.Add(other);
if (!m_isPressed)
{
m_isPressed = true;
OnPressed?.Invoke();
}
}
private void OnTriggerStay(Collider other)
{
if (IsValidActivator(other))
m_stayedThisPhysicsFrame.Add(other);
}
private void OnTriggerExit(Collider other)
{
m_stayedThisPhysicsFrame.Remove(other);
if (!m_validCollidersOnPlate.Remove(other))
return;
if (m_validCollidersOnPlate.Count == 0 && m_isPressed)
{
m_isPressed = false;
OnReleased?.Invoke();
}
}
private void FixedUpdate()
{
if (m_validCollidersOnPlate.Count == 0)
{
m_stayedThisPhysicsFrame.Clear();
return;
}
m_validCollidersOnPlate.RemoveWhere(c => c == null || !c.enabled || !c.gameObject.activeInHierarchy);
m_validCollidersOnPlate.IntersectWith(m_stayedThisPhysicsFrame);
m_stayedThisPhysicsFrame.Clear();
if (m_validCollidersOnPlate.Count == 0 && m_isPressed)
{
m_isPressed = false;
OnReleased?.Invoke();
}
}
private bool IsValidActivator(Collider other)
{
if (((1 << other.gameObject.layer) & detectionMask) == 0)
return false;
if (allowPlayer)
{
if (other.CompareTag("Player"))
return true;
if (other.GetComponentInParent<PlayerMovement>() != null)
return true;
}
if (allowRigidbodies && other.attachedRigidbody != null)
return true;
return false;
}
}