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;
}
}
}
}
}