/// --------------------------------------------- /// Ultimate Character Controller /// Copyright (c) Opsive. All Rights Reserved. /// https://www.opsive.com /// --------------------------------------------- namespace Opsive.UltimateCharacterController.Character.Abilities { using Opsive.Shared.Events; using UnityEngine; /// /// The Start Movement ability allows the character to play a starting animation. /// [DefaultStopType(AbilityStopType.Automatic)] [DefaultAbilityIndex(6)] public class QuickStart : StoredInputAbilityBase { [Tooltip("The value which differentiates between a walk and a run.")] [SerializeField] protected float m_SpeedChangeThreshold = 1; public float SpeedChangeThreshold { get { return m_SpeedChangeThreshold; } set { m_SpeedChangeThreshold = value; } } private enum StartIndex { None, WalkForward, WalkForwardTurnLeft, WalkForwardTurnRight, WalkStrafeLeft, WalkStrafeRight, WalkBackward, WalkBackwardTurnLeft, WalkBackwardTurnRight, RunForward, RunForwardTurnLeft, RunForwardTurnRight, RunStrafeLeft, RunStrafeRight, RunBackward, RunBackwardTurnLeft, RunBackwardTurnRight } private bool m_CanStart; private int m_StartIndex; private bool m_EventStop; protected override bool UseRawInput { get { return true; } } protected override bool RequireInput { get { return false; } } public override int AbilityIntData { get { return m_StartIndex; } } /// /// Initialize the default values. /// public override void Awake() { base.Awake(); EventHandler.RegisterEvent(m_GameObject, "OnAnimatorStartMovementComplete", OnStartComplete); EventHandler.RegisterEvent(m_GameObject, "OnCharacterMoving", OnMoving); } /// /// The character has started to or stopped moving. /// /// Is the character moving? private void OnMoving(bool moving) { if (!moving) { // The ability can't start until the character is no longer moving. This will prevent the ability from starting repeatedly // while the character is moving. m_CanStart = true; } } /// /// Called when the ablity is tried to be started. If false is returned then the ability will not be started. /// /// True if the ability can be started. public override bool CanStartAbility() { if (!base.CanStartAbility()) { return false; } // The ability can't start if the character is stopped. if (m_CharacterLocomotion.InputVector.sqrMagnitude == 0) { return false; } // If the input count is greater than zero then the character has been moving already so the ability should not be started. if (m_InputCount > 0) { m_CanStart = false; } return m_CanStart; } /// /// The ability has started. /// protected override void AbilityStarted() { // The start index is based on the input value. var inputValue = m_CharacterLocomotion.InputVector; m_StartIndex = (int)StartIndex.None; if (inputValue.x > m_SpeedChangeThreshold && inputValue.y > m_SpeedChangeThreshold) { m_StartIndex = (int)StartIndex.RunForwardTurnRight; } else if (inputValue.x > 0 && inputValue.y > 0) { m_StartIndex = (int)StartIndex.WalkForwardTurnRight; } else if (inputValue.x < -m_SpeedChangeThreshold && inputValue.y > m_SpeedChangeThreshold) { m_StartIndex = (int)StartIndex.RunForwardTurnLeft; } else if (inputValue.x < 0 && inputValue.y > 0) { m_StartIndex = (int)StartIndex.WalkForwardTurnLeft; } else if (inputValue.x < -m_SpeedChangeThreshold && inputValue.y < -m_SpeedChangeThreshold) { m_StartIndex = (int)StartIndex.RunBackwardTurnLeft; } else if (inputValue.x < 0 && inputValue.y < 0) { m_StartIndex = (int)StartIndex.WalkBackwardTurnLeft; } else if (inputValue.x > m_SpeedChangeThreshold && inputValue.y < -m_SpeedChangeThreshold) { m_StartIndex = (int)StartIndex.RunBackwardTurnRight; } else if (inputValue.x > 0 && inputValue.y < 0) { m_StartIndex = (int)StartIndex.WalkBackwardTurnRight; } else if (inputValue.y > m_SpeedChangeThreshold) { m_StartIndex = (int)StartIndex.RunForward; } else if (inputValue.y > 0) { m_StartIndex = (int)StartIndex.WalkForward; } else if (inputValue.y < -m_SpeedChangeThreshold) { m_StartIndex = (int)StartIndex.RunBackward; } else if (inputValue.y < 0) { m_StartIndex = (int)StartIndex.WalkBackward; } else if (inputValue.x > m_SpeedChangeThreshold) { m_StartIndex = (int)StartIndex.RunStrafeRight; } else if (inputValue.x > 0) { m_StartIndex = (int)StartIndex.WalkStrafeRight; } else if (inputValue.x < -m_SpeedChangeThreshold) { m_StartIndex = (int)StartIndex.RunStrafeLeft; } else if (inputValue.x < 0) { m_StartIndex = (int)StartIndex.WalkStrafeLeft; } m_EventStop = false; m_CanStart = false; base.AbilityStarted(); } /// /// Can the ability be stopped? /// /// True if the ability can be stopped. public override bool CanStopAbility() { return m_EventStop || m_CharacterLocomotion.RawInputVector.sqrMagnitude == 0; } /// /// Animation event callback when the start animation has completed. /// private void OnStartComplete() { m_EventStop = true; } /// /// Called when the character is destroyed. /// public override void OnDestroy() { base.OnDestroy(); EventHandler.UnregisterEvent(m_GameObject, "OnAnimatorStartMovementComplete", OnStartComplete); EventHandler.UnregisterEvent(m_GameObject, "OnCharacterMoving", OnMoving); } } }