Last active
April 5, 2022 07:29
-
-
Save sim2kid/d51021c9346db614d3ec9a36fe665d3f to your computer and use it in GitHub Desktop.
A tool used to make sure TriggerExit is reliably called for a MonoBehavior. This will ensure when a collider is disabled, your exit events still happens outside of it.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections; | |
using System.Collections.Generic; | |
using UnityEngine; | |
using System.Linq; | |
/// <summary> | |
/// A tool used to make sure TriggerExit is reliably called for a MonoBehavior. This will ensure when a collider is disabled, your exit events still happens outside of it. | |
/// Just hook in the AddTrigger, FixedUpdate, and RemoveTrigger to your OnTriggerEnter, FixedUpdate, and OnTriggerExit to get started. | |
/// </summary> | |
public class TrackTrigger | |
{ | |
public delegate void OnTriggerExit(Collider other); | |
private List<TriggerFrame> Triggers = new List<TriggerFrame>(); | |
private GameObject origin; | |
public TrackTrigger(GameObject origin) | |
{ | |
this.origin = origin; | |
} | |
/// <summary> | |
/// Called in "OnTriggerEnter" to start tracking the trigger | |
/// </summary> | |
/// <param name="other">The other collider passed into OnTriggerEvent</param> | |
/// <param name="callback">The "OnTriggerExit" function</param> | |
public void AddTrigger(Collider other, OnTriggerExit callback) | |
{ | |
if (!Contains(other)) | |
{ | |
Triggers.Add(new TriggerFrame(other, callback)); | |
} | |
} | |
/// <summary> | |
/// Hooked into the FixedUpdate loop. This will check the triggers to see if they need to be removed. | |
/// </summary> | |
public void FixedUpdate() | |
{ | |
// Remove dead triggers first | |
Triggers.RemoveAll(x => x.removed); | |
// Check Triggers. | |
foreach (var trigger in Triggers) | |
{ | |
// If they haven't been called last frame... | |
if (trigger.calledLastFrame == false) | |
{ | |
// Register them for removal | |
if (trigger.removed != true) | |
{ | |
// And run a callback | |
TriggerCallback(trigger); | |
trigger.removed = true; | |
} | |
} | |
// Set all triggers to false. | |
trigger.calledLastFrame = false; | |
} | |
} | |
/// <summary> | |
/// Called in the OnTriggerStay loop. This lets us know the trigger still exists | |
/// </summary> | |
/// <param name="other"></param> | |
public void TriggerUpdate(Collider other) | |
{ | |
// Set the trigger to True | |
var tFrame = Find(other); | |
if (tFrame != null) | |
{ | |
tFrame.calledLastFrame = true; | |
} | |
} | |
/// <summary> | |
/// Called in the OnTriggerExit method to let us know the trigger has been removed. | |
/// </summary> | |
/// <param name="other"></param> | |
public void RemoveTrigger(Collider other) | |
{ | |
// Schedules a trigger for removal but won't remove it until next update | |
Find(other).removed = true; | |
} | |
private void TriggerCallback(TriggerFrame frame) | |
{ | |
frame.callback.Invoke(frame.collider); | |
} | |
private TriggerFrame Find(Collider other) | |
{ | |
return Triggers.FirstOrDefault(x => x.collider.Equals(other)); | |
} | |
private bool Contains(Collider other) | |
{ | |
return Triggers.Any(x => x.collider.Equals(other)); | |
} | |
private class TriggerFrame : System.IEquatable<TriggerFrame> | |
{ | |
public Collider collider; | |
public bool calledLastFrame; | |
public bool removed; | |
public OnTriggerExit callback; | |
public TriggerFrame(Collider other, OnTriggerExit callback) | |
{ | |
collider = other; | |
this.callback = callback; | |
calledLastFrame = true; | |
removed = false; | |
} | |
public bool Equals(TriggerFrame other) | |
{ | |
return collider.Equals(other.collider); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections; | |
using System.Collections.Generic; | |
using UnityEngine; | |
public class TrackTriggerUsage : MonoBehaviour | |
{ | |
private TrackTrigger triggerEvent; | |
void Start() | |
{ | |
triggerEvent = new TrackTrigger(gameObject); | |
} | |
private void FixedUpdate() | |
{ | |
triggerEvent.FixedUpdate(); | |
} | |
private void OnTriggerStay(Collider other) | |
{ | |
triggerEvent.TriggerUpdate(other); | |
} | |
private void OnTriggerEnter(Collider other) | |
{ | |
triggerEvent.AddTrigger(other, OnTriggerExit); | |
} | |
private void OnTriggerExit(Collider other) | |
{ | |
triggerEvent.RemoveTrigger(other); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment