106 lines
2.8 KiB
C#
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;
|
|
}
|
|
}
|