/// --------------------------------------------- /// Ultimate Character Controller /// Copyright (c) Opsive. All Rights Reserved. /// https://www.opsive.com /// --------------------------------------------- namespace Opsive.UltimateCharacterController.Character.Effects { using Opsive.Shared.Events; using Opsive.Shared.Utility; using Opsive.UltimateCharacterController.Camera; using Opsive.UltimateCharacterController.StateSystem; using Opsive.UltimateCharacterController.Utility; using UnityEngine; /// /// Effects allow for extra camera/item movements that are applied to the character. Examples of an effect include an earthquake shake or a boss stomp. Effects /// do not affect the Animator and are not synchronized over the network. For anything more involved an Ability should be used instead. /// [System.Serializable] [UnityEngine.Scripting.Preserve] [AllowDuplicateTypes] public abstract class Effect : StateObject { [Tooltip("Can the ability be activated?")] [HideInInspector] [SerializeField] protected bool m_Enabled = true; [Tooltip("Should the effect be started when it is enabled?")] [SerializeField] protected bool m_StartWhenEnabled; [Tooltip("Specifies the name of the state that the effect should activate.")] [SerializeField] protected string m_State; #if UNITY_EDITOR [Tooltip("An editor only description of the effect.")] [HideInInspector] [SerializeField] protected string m_InspectorDescription; #endif public bool Enabled { get { return m_Enabled; } set { if (m_Enabled == value) { return; } m_Enabled = value; if (!m_Enabled && IsActive) { StopEffect(false); } else if (Application.isPlaying && m_Enabled && !IsActive && m_StartWhenEnabled) { StartEffect(); } } } #if UNITY_EDITOR public string InspectorDescription { get { return m_InspectorDescription; } set { m_InspectorDescription = value; } } #endif public bool StartWhenEnabled { get { return m_StartWhenEnabled; } set { m_StartWhenEnabled = value; } } protected GameObject m_GameObject; protected Transform m_Transform; protected UltimateCharacterLocomotion m_CharacterLocomotion; protected CameraController m_CameraController; private int m_ActiveIndex = -1; private int m_Index = -1; public bool IsActive { get { return m_ActiveIndex != -1; } } [NonSerialized] public int Index { get { return m_Index; } set { m_Index = value; } } [NonSerialized] public int ActiveIndex { get { return m_ActiveIndex; } set { m_ActiveIndex = value; } } /// /// Initializes the effect to the specified controller. /// /// The character locomotion component to initialize the effect to. /// The prioirty index of the ability within the controller. public void Initialize(UltimateCharacterLocomotion characterLocomotion, int index) { m_CharacterLocomotion = characterLocomotion; m_GameObject = characterLocomotion.gameObject; m_Transform = characterLocomotion.transform; m_Index = index; // The StateObject class needs to initialize itself. Initialize(m_GameObject); } /// /// Method called by MonoBehaviour.Awake. Can be used for initialization. /// public virtual void Awake() { EventHandler.RegisterEvent(m_GameObject, "OnCharacterAttachCamera", OnAttachCamera); } /// /// Method called by MonoBehaviour.Start. This method is called on all effects when the MonoBehaviour.Start method is called. /// public virtual void Start() { } /// /// Can the effect be started? /// /// True if the effect can be started. public virtual bool CanStartEffect() { return true; } /// /// Tries to start the effect. /// /// True if the effect was successfully started. public bool StartEffect() { return m_CharacterLocomotion.TryStartEffect(this); } /// /// Starts executing the effect. /// public void StartEffect(int index) { m_ActiveIndex = index; EffectStarted(); } /// /// The effect has been started. /// protected virtual void EffectStarted() { if (!string.IsNullOrEmpty(m_State)) { StateManager.SetState(m_GameObject, m_State, true); } } /// /// Updates the effect. Called during the MonoBehaviour.Update loop. /// public virtual void Update() { } /// /// Stop the effect from running. /// public void StopEffect() { StopEffect(false); } /// /// Stop the effect from running. /// /// Is the effect being stopped from the UltimateCharacterController? public void StopEffect(bool fromController) { // If the effect wasn't stopped from the character controller then call the controller's stop effect method. The controller must be aware of the stopping. if (!fromController) { m_CharacterLocomotion.TryStopEffect(this); return; } m_ActiveIndex = -1; EffectStopped(); } /// /// The effect has stopped running. /// protected virtual void EffectStopped() { if (!string.IsNullOrEmpty(m_State)) { StateManager.SetState(m_GameObject, m_State, false); } } /// /// The character has been attached to the camera. Initialze the camera-related values. /// /// The camera controller attached to the character. Can be null. private void OnAttachCamera(CameraController cameraController) { m_CameraController = cameraController; } /// /// Called when the character is destroyed. /// public virtual void OnDestroy() { EventHandler.UnregisterEvent(m_GameObject, "OnCharacterAttachCamera", OnAttachCamera); } } }