// Animancer // Copyright 2020 Kybernetik // #pragma warning disable CS0649 // Field is never assigned to, and will always have its default value. using System; using UnityEngine; namespace Animancer.Examples.AnimatorControllers.GameKit { /// /// A which keeps the creature standing still. /// [AddComponentMenu(Strings.MenuPrefix + "Examples/Game Kit - Idle State")] [HelpURL(Strings.APIDocumentationURL + ".Examples.AnimatorControllers.GameKit/IdleState")] public sealed class IdleState : CreatureState { /************************************************************************************************************************/ [SerializeField] private ClipState.Transition _MainAnimation; [SerializeField] private float _FirstRandomizeDelay = 5; [SerializeField] private float _MinRandomizeInterval = 0; [SerializeField] private float _MaxRandomizeInterval = 20; [SerializeField] private ClipState.Transition[] _RandomAnimations; private float _RandomizeTime; // _RandomizeDelay was originally handled by the PlayerController (Idle Timeout). // The min and max interval were handled by the RandomStateSMB on the Idle state in IdleSM. /************************************************************************************************************************/ private void Awake() { Action onEnd = PlayMainAnimation; for (int i = 0; i < _RandomAnimations.Length; i++) { _RandomAnimations[i].Events.Sequence.OnEnd = onEnd; // We could just do `OnEnd = PlayMainAnimation` instead of declaring the delegate first, but that // assignment is actually shorthand for `new Action(PlayMainAnimation)` which would create a new // delegate object for each animation. This way all animations just share the same object. } } /************************************************************************************************************************/ public override bool CanEnterState(CreatureState previousState) { return Creature.CharacterController.isGrounded; } /************************************************************************************************************************/ private void OnEnable() { PlayMainAnimation(); _RandomizeTime += _FirstRandomizeDelay; } private void PlayMainAnimation() { _RandomizeTime = UnityEngine.Random.Range(_MinRandomizeInterval, _MaxRandomizeInterval); Creature.Animancer.Play(_MainAnimation); } /************************************************************************************************************************/ private void FixedUpdate() { if (Creature.CheckMotionState()) return; Creature.UpdateSpeedControl(); // We use time where Mecanim used normalized time because choosing a number of seconds is much simpler than // finding out how long the animation is and working with multiples of that value. if (Creature.Animancer.States.Current == _MainAnimation.State && Creature.Animancer.States.Current.Time >= _RandomizeTime) { PlayRandomAnimation(); } } /************************************************************************************************************************/ private void PlayRandomAnimation() { var index = UnityEngine.Random.Range(0, _RandomAnimations.Length); var animation = _RandomAnimations[index]; Creature.Animancer.Play(animation); } /************************************************************************************************************************/ } }