Files
2025-09-16 18:07:13 +07:00

96 lines
3.9 KiB
C#

// Animancer // https://kybernetik.com.au/animancer // Copyright 2021 Kybernetik //
#pragma warning disable CS0649 // Field is never assigned to, and will always have its default value.
using UnityEngine;
namespace Animancer.Examples.FineControl
{
/// <summary>
/// Demonstrates how to play a single "Wake Up" animation forwards to wake up and backwards to go back to sleep.
/// </summary>
///
/// <remarks>
/// This is an abstract class which is inherited by <see cref="SpiderBotSimple"/> and
/// <see cref="Locomotion.SpiderBotAdvanced"/>, meaning that you cannot attach this script to an object (because it
/// would be useless on its own) and both of those scripts get to share its functionality without needing to copy
/// the same methods into each of them.
/// </remarks>
///
/// <example><see href="https://kybernetik.com.au/animancer/docs/examples/fine-control/spider-bot">Spider Bot</see></example>
///
/// https://kybernetik.com.au/animancer/api/Animancer.Examples.FineControl/SpiderBot
///
[AddComponentMenu(Strings.ExamplesMenuPrefix + "Fine Control - Spider Bot")]
[HelpURL(Strings.DocsURLs.ExampleAPIDocumentation + nameof(FineControl) + "/" + nameof(SpiderBot))]
public abstract class SpiderBot : MonoBehaviour
{
/************************************************************************************************************************/
[SerializeField]
private AnimancerComponent _Animancer;
public AnimancerComponent Animancer => _Animancer;
[SerializeField] private ClipTransition _WakeUp;
[SerializeField] private ClipTransition _Sleep;
private bool _WasMoving;
/************************************************************************************************************************/
protected abstract bool IsMoving { get; }
protected abstract ITransition MovementAnimation { get; }
/************************************************************************************************************************/
protected virtual void Awake()
{
// Start paused at the beginning of the animation.
_Animancer.Play(_WakeUp);
_Animancer.Evaluate();
_Animancer.Playable.PauseGraph();
// Initialize the OnEnd events here so we don't allocate garbage every time they are used.
_WakeUp.Events.OnEnd = () => _Animancer.Play(MovementAnimation);
_Sleep.Events.OnEnd = _Animancer.Playable.PauseGraph;
}
/************************************************************************************************************************/
protected virtual void Update()
{
if (IsMoving)
{
if (!_WasMoving)
{
_WasMoving = true;
// Make sure the graph is unpaused (because we pause it when going back to sleep).
_Animancer.Playable.UnpauseGraph();
_Animancer.Play(_WakeUp);
}
}
else
{
if (_WasMoving)
{
_WasMoving = false;
var state = _Animancer.Play(_Sleep);
// If it was past the last frame, skip back to the last frame now that it is playing backwards.
// Otherwise just play backwards from the current time.
if (state.NormalizedTime > 1)
state.NormalizedTime = 1;
// If we did not initialize the OnEnd event in Awake, we could set it here:
// state.OnEnd = _Animancer.Playable.PauseGraph;
}
}
}
/************************************************************************************************************************/
}
}