I wanted to use AnimationRigging+Animator to edit my IK effects in the editor environment. Since LateUpdate does not exist in the editor environment, I manually updated the Animator and RigBuilder via the tick of the Application. We set the SortingOrder of AnimationPlayableOutput to ensure that the Rig process is after the Animator output, but we still don’t see the correct IK effect. What could be the reason?
Here is code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEngine.Animations;
using UnityEngine.Animations.Rigging;
using UnityEngine.Experimental.Animations;
public class TestEditorAnimationWindow : EditorWindow
{
[MenuItem("Window/TestEditorAnimationWindow")]
private static void OpenWindow()
{
var window = GetWindow<TestEditorAnimationWindow>();
window.Show();
}
private Animator animator;
private RigBuilder rigBuidler;
public void OnEnable()
{
EditorApplication.update += MyUpdate;
GameObject go = GameObject.Find("bb04_preview_prefab");
animator = go.GetComponentInChildren<Animator>();
AnimationPlayableOutput output = (AnimationPlayableOutput)animator.playableGraph.GetOutput(0);
output.SetSortingOrder(200);
animator.playableGraph.SetTimeUpdateMode(UnityEngine.Playables.DirectorUpdateMode.Manual);
rigBuidler = go.GetComponentInChildren<RigBuilder>();
rigBuidler.enabled = false;
if (rigBuidler.Build())
{
rigBuidler.graph.SetTimeUpdateMode(UnityEngine.Playables.DirectorUpdateMode.Manual);
}
}
public void OnDisable()
{
EditorApplication.update -= MyUpdate;
rigBuidler.Clear();
}
void MyUpdate()
{
if (animator != null)
{
animator.Update(Time.deltaTime);
rigBuidler.Evaluate(Time.deltaTime);
}
}
}
This is not consistent with my needs.
What I want is to play a specific animation in the Editor environment that I’ve already put into the animator, so I tick the animator manually;
The animator output is then post-processed using Rig to preview the result in the editor environment
I got a workable solution: Replace the default animatorController with playable!
I knew the animator was the problem, but I didn’t know why yet, so my solution was to use the playable dynamic to create a playgraph, insert the playable created by rigBuilder to the end of the playgraph, and implement a post-processing effect. It worked.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEngine.Animations;
using UnityEngine.Animations.Rigging;
using UnityEngine.Experimental.Animations;
using UnityEngine.Playables;
public class TestEditorAnimationWindow : EditorWindow
{
[MenuItem("Window/TestEditorAnimationWindow")]
private static void OpenWindow()
{
var window = GetWindow<TestEditorAnimationWindow>();
window.Show();
}
private Animator animator;
private Playable root;
private AnimationPlayableOutput output;
private PlayableGraph graph;
private float accTime = 0f;
private RigBuilder rigBuidler;
public void OnEnable()
{
EditorApplication.update += MyUpdate;
GameObject go = GameObject.Find("bb04_preview_prefab");
animator = go.GetComponentInChildren<Animator>();
graph = PlayableGraph.Create("TestAnimator");
output = AnimationPlayableOutput.Create(graph, "TestOutput", animator);
output.SetWeight(1f);
var clip = LoadAnimationClip("xxx.fbx");
root = AnimationClipPlayable.Create(graph, clip);
output.SetSourcePlayable(root);
graph.Play();
accTime = 0f;
rigBuidler = go.GetComponentInChildren<RigBuilder>();
rigBuidler.Clear();
var newRoot = rigBuidler.BuildPreviewGraph(graph, root);
output.SetSourcePlayable(newRoot);
}
public void OnDisable()
{
rigBuidler.Clear();
graph.Destroy();
EditorApplication.update -= MyUpdate;
}
void MyUpdate()
{
accTime += Time.deltaTime;
root.SetTime(accTime);
rigBuidler.SyncLayers();
graph.Evaluate();
}
private AnimationClip LoadAnimationClip(string path)
{
return AssetDatabase.LoadAssetAtPath<AnimationClip>(path);
}
}