106 lines
4.5 KiB
C#
106 lines
4.5 KiB
C#
// Animancer // https://kybernetik.com.au/animancer // Copyright 2018-2024 Kybernetik //
|
|
|
|
#pragma warning disable CS0649 // Field is never assigned to, and will always have its default value.
|
|
|
|
using Animancer.Units;
|
|
using System;
|
|
using UnityEngine;
|
|
|
|
namespace Animancer.Samples.AnimatorControllers.GameKit
|
|
{
|
|
/// <summary>
|
|
/// A <see cref="CharacterState"/> which keeps the character standing still and occasionally plays alternate
|
|
/// animations if it remains active for long enough.
|
|
/// </summary>
|
|
///
|
|
/// <remarks>
|
|
/// <strong>Sample:</strong>
|
|
/// <see href="https://kybernetik.com.au/animancer/docs/samples/animator-controllers/3d-game-kit/idle">
|
|
/// 3D Game Kit/Idle</see>
|
|
/// </remarks>
|
|
///
|
|
/// https://kybernetik.com.au/animancer/api/Animancer.Samples.AnimatorControllers.GameKit/IdleState
|
|
///
|
|
[AddComponentMenu(Strings.SamplesMenuPrefix + "Game Kit - Idle State")]
|
|
[AnimancerHelpUrl(typeof(IdleState))]
|
|
public class IdleState : CharacterState
|
|
{
|
|
/************************************************************************************************************************/
|
|
|
|
[SerializeField] private ClipTransition _MainAnimation;
|
|
[SerializeField, Seconds] private float _FirstRandomizeDelay = 5;
|
|
[SerializeField, Seconds] private float _MinRandomizeInterval = 0;
|
|
[SerializeField, Seconds] private float _MaxRandomizeInterval = 20;
|
|
[SerializeField] private ClipTransition[] _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.
|
|
|
|
/************************************************************************************************************************/
|
|
|
|
protected virtual void Awake()
|
|
{
|
|
Action onEnd = PlayMainAnimation;
|
|
for (int i = 0; i < _RandomAnimations.Length; i++)
|
|
{
|
|
_RandomAnimations[i].Events.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 => Character.Movement.IsGrounded;
|
|
|
|
/************************************************************************************************************************/
|
|
|
|
protected virtual void OnEnable()
|
|
{
|
|
PlayMainAnimation();
|
|
_RandomizeTime += _FirstRandomizeDelay;
|
|
}
|
|
|
|
private void PlayMainAnimation()
|
|
{
|
|
_RandomizeTime = UnityEngine.Random.Range(_MinRandomizeInterval, _MaxRandomizeInterval);
|
|
Character.Animancer.Play(_MainAnimation);
|
|
}
|
|
|
|
/************************************************************************************************************************/
|
|
|
|
protected virtual void FixedUpdate()
|
|
{
|
|
if (Character.CheckMotionState())
|
|
return;
|
|
|
|
Character.Movement.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.
|
|
AnimancerState state = Character.Animancer.States.Current;
|
|
if (state == _MainAnimation.State &&
|
|
state.Time >= _RandomizeTime)
|
|
{
|
|
PlayRandomAnimation();
|
|
}
|
|
}
|
|
|
|
/************************************************************************************************************************/
|
|
|
|
private void PlayRandomAnimation()
|
|
{
|
|
int index = UnityEngine.Random.Range(0, _RandomAnimations.Length);
|
|
ClipTransition animation = _RandomAnimations[index];
|
|
AnimancerState state = Character.Animancer.Play(animation);
|
|
state.FadeGroup.SetEasing(Easing.Sine.InOut);
|
|
}
|
|
|
|
/************************************************************************************************************************/
|
|
}
|
|
}
|