Files
RebootKit/Runtime/Engine/Code/Animations/ReAnimator.cs
2025-09-16 20:47:15 +02:00

87 lines
2.4 KiB
C#

using System;
using UnityEngine;
using UnityEngine.Animations;
using UnityEngine.Assertions;
using UnityEngine.Playables;
using Logger = RebootKit.Engine.Foundation.Logger;
// @TODO:
// - avoid boxing values
// - think about refactoring in order to reduce gc allocs
namespace RebootKit.Engine.Animations {
public interface IReAnimatorNode {
string Name { get; }
void Tick(float deltaTime);
IPlayable Build(PlayableGraph graph);
bool TryFindChild(string name, out IReAnimatorNode node);
}
public enum ReAnimatorTickMode {
Update,
Fixed,
Manual
}
[DefaultExecutionOrder(-100)]
public class ReAnimator : MonoBehaviour {
static readonly Logger s_Logger = new Logger(nameof(ReAnimator));
[SerializeField] Animator m_Animator;
[SerializeField] LayerMixerNode m_Root;
public PlayableGraph Graph { get; private set; }
AnimationPlayableOutput m_Output;
void Awake() {
Assert.IsNotNull(m_Animator, "Animator is not set");
m_Animator.runtimeAnimatorController = null;
Graph = PlayableGraph.Create(name);
m_Output = AnimationPlayableOutput.Create(Graph, "Animation Output", m_Animator);
if (m_Root.Build(Graph) is AnimationLayerMixerPlayable layerMixer) {
m_Output.SetSourcePlayable(layerMixer, 0);
}
Graph.Play();
}
void OnDestroy() {
if (Graph.IsValid()) {
Graph.Destroy();
}
}
void Update() {
float dt = Time.deltaTime;
m_Root.Tick(dt);
Graph.Evaluate(dt);
}
public void SetLayerWeight(int layer, float weight) {
m_Root.SetLayerWeight(layer, weight);
}
public IReAnimatorNode FindNode(string nodeName) {
if (m_Root.TryFindChild(nodeName, out IReAnimatorNode node)) {
return node;
}
s_Logger.Error($"Couldn't find node with name: {nodeName}");
return null;
}
public TNode FindNode<TNode>(string nodeName) where TNode : class, IReAnimatorNode {
IReAnimatorNode node = FindNode(nodeName);
if (node is TNode tnode) {
return tnode;
}
s_Logger.Error($"Couldn't find node with name: {nodeName} of type {typeof(TNode).Name}");
return null;
}
}
}