using UnityEngine; using System.Collections; using UnityEngine.Events; using System.Collections.Generic; namespace MoreMountains.Tools { /// /// Add this component to an object and it'll be auto destroyed X seconds after its Start() /// [AddComponentMenu("More Mountains/Tools/Activation/MMTimedActivation")] public class MMTimedActivation : MonoBehaviour { /// the possible activation modes public enum TimedStatusChange { Enable, Disable, Destroy } /// the possible trigger modes public enum ActivationModes { Awake, Start, OnEnable, OnTriggerEnter, OnTriggerExit, OnTriggerEnter2D, OnTriggerExit2D, Script } /// the possible ways to check if the collider matches public enum TriggerModes { None, Tag, Layer } /// the possible delay modes public enum DelayModes { Time, Frames } [Header("Trigger Mode")] /// the moment you want the countdown to state change to start public ActivationModes ActivationMode = ActivationModes.Start; /// the target layer for activation if using OnTriggerEnter or OnTriggerExit [MMEnumCondition("ActivationMode", (int)ActivationModes.OnTriggerEnter, (int)ActivationModes.OnTriggerExit)] public TriggerModes TriggerMode; /// the layer the target collider should be on [MMEnumCondition("TriggerMode", (int)TriggerModes.Layer)] public LayerMask TargetTriggerLayer; /// the tag the target collider should have [MMEnumCondition("TriggerMode", (int)TriggerModes.Tag)] public string TargetTriggerTag; [Header("Delay")] /// the chosen delay mode, whether to wait in seconds or frames public DelayModes DelayMode = DelayModes.Time; /// The time (in seconds) before we destroy the object [MMEnumCondition("DelayMode", (int)DelayModes.Time)] public float TimeBeforeStateChange = 2; /// the amount of frames to wait for when in Frames DelayMode [MMEnumCondition("DelayMode", (int)DelayModes.Frames)] public int FrameCount = 1; [Header("Timed Activation")] /// the possible targets you want the state to change public List TargetGameObjects; /// the possible targets you want the state to change public List TargetBehaviours; /// the destruction mode for this object : destroy or disable public TimedStatusChange TimeDestructionMode = TimedStatusChange.Disable; [Header("Actions")] /// Unity events to trigger after the delay public UnityEvent TimedActions; /// /// On awake, initialize our delay and trigger our change state countdown if needed /// protected virtual void Awake() { if (ActivationMode == ActivationModes.Awake) { StartChangeState(); } } /// /// Call this method to start the countdown to activation /// public virtual void TriggerSequence() { StartChangeState(); } /// /// On start, trigger our change state countdown if needed /// protected virtual void Start() { if (ActivationMode == ActivationModes.Start) { StartChangeState(); } } /// /// On enable, trigger our change state countdown if needed /// protected virtual void OnEnable() { if (ActivationMode == ActivationModes.Start) { StartChangeState(); } } /// /// On trigger enter, we start our countdown if needed /// /// protected virtual void OnTriggerEnter(Collider collider) { if ((ActivationMode == ActivationModes.OnTriggerEnter) && (CorrectTagOrLayer(collider.gameObject))) { StartChangeState(); } } /// /// On trigger exit, we start our countdown if needed /// /// protected virtual void OnTriggerExit(Collider collider) { if ((ActivationMode == ActivationModes.OnTriggerEnter) && (CorrectTagOrLayer(collider.gameObject))) { StartChangeState(); } } /// /// On trigger enter 2D, we start our countdown if needed /// /// protected virtual void OnTriggerEnter2d(Collider2D collider) { if ((ActivationMode == ActivationModes.OnTriggerEnter) && (CorrectTagOrLayer(collider.gameObject))) { StartChangeState(); } } /// /// On trigger exit 2D, we start our countdown if needed /// /// protected virtual void OnTriggerExit2d(Collider2D collider) { if ((ActivationMode == ActivationModes.OnTriggerEnter) && (CorrectTagOrLayer(collider.gameObject))) { StartChangeState(); } } /// /// Returns true if the target matches our settings, false otherwise /// /// /// protected virtual bool CorrectTagOrLayer(GameObject target) { switch (TriggerMode) { case TriggerModes.None: return true; case TriggerModes.Layer: if (((1 << target.layer) & TargetTriggerLayer) != 0) { return true; } else { return false; } case TriggerModes.Tag: return (target.CompareTag(TargetTriggerTag)); } return false; } /// /// On start change state, starts the timed activation /// protected virtual void StartChangeState() { StartCoroutine(TimedActivationSequence()); } /// /// Waits and triggers state change and events /// protected virtual IEnumerator TimedActivationSequence() { if (DelayMode == DelayModes.Time) { yield return MMCoroutine.WaitFor(TimeBeforeStateChange); } else { yield return StartCoroutine(MMCoroutine.WaitForFrames(FrameCount)); } StateChange(); Activate(); } /// /// Triggers actions if needed /// protected virtual void Activate() { if (TimedActions != null) { TimedActions.Invoke(); } } /// /// Changes the object's status or destroys it /// protected virtual void StateChange() { foreach(GameObject targetGameObject in TargetGameObjects) { switch (TimeDestructionMode) { case TimedStatusChange.Destroy: Destroy(targetGameObject); break; case TimedStatusChange.Disable: targetGameObject.SetActive(false); break; case TimedStatusChange.Enable: targetGameObject.SetActive(true); break; } } foreach (MonoBehaviour targetBehaviour in TargetBehaviours) { switch (TimeDestructionMode) { case TimedStatusChange.Destroy: Destroy(targetBehaviour); break; case TimedStatusChange.Disable: targetBehaviour.enabled = false; break; case TimedStatusChange.Enable: targetBehaviour.enabled = true; break; } } } } }