fix: occasionally objects controlling reactive components "flicker" (#1298)

Reported-by: @whipnice
This commit is contained in:
bd_ 2024-10-19 17:15:14 -07:00 committed by GitHub
parent 3ba0219430
commit ae975506d7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -1,9 +1,11 @@
using System.Linq;
using nadena.dev.modular_avatar.core.editor;
using nadena.dev.ndmf;
using UnityEditor;
using UnityEditor.Animations;
using UnityEngine;
using VRC.SDK3.Avatars.Components;
using BuildContext = nadena.dev.ndmf.BuildContext;
namespace nadena.dev.modular_avatar.animation
{
@ -23,11 +25,16 @@ namespace nadena.dev.modular_avatar.animation
if (fx == null) return;
var nullMotion = new AnimationClip();
nullMotion.name = "NullMotion";
var blendTree = new BlendTree();
blendTree.blendType = BlendTreeType.Direct;
blendTree.useAutomaticThresholds = false;
blendTree.children = asc.BoundReadableProperties.Select(GenerateDelayChild).ToArray();
blendTree.children = asc.BoundReadableProperties
.Select(prop => GenerateDelayChild(nullMotion, prop))
.ToArray();
var asm = new AnimatorStateMachine();
var state = new AnimatorState();
@ -54,7 +61,7 @@ namespace nadena.dev.modular_avatar.animation
}).ToArray();
}
private ChildMotion GenerateDelayChild((EditorCurveBinding, string) binding)
private ChildMotion GenerateDelayChild(Motion nullMotion, (EditorCurveBinding, string) binding)
{
var ecb = binding.Item1;
var prop = binding.Item2;
@ -64,10 +71,40 @@ namespace nadena.dev.modular_avatar.animation
curve.AddKey(0, 1);
AnimationUtility.SetEditorCurve(motion, ecb, curve);
// Occasionally, we'll have a very small value pop up, probably due to FP errors.
// To correct for this, instead of directly using the property in the direct blend tree,
// we'll use a 1D blend tree to give ourselves a buffer.
var bufferBlendTree = new BlendTree();
bufferBlendTree.blendType = BlendTreeType.Simple1D;
bufferBlendTree.useAutomaticThresholds = false;
bufferBlendTree.blendParameter = prop;
bufferBlendTree.children = new[]
{
new ChildMotion
{
motion = nullMotion,
timeScale = 1,
threshold = 0
},
new ChildMotion
{
motion = nullMotion,
timeScale = 1,
threshold = 0.01f
},
new ChildMotion
{
motion = motion,
timeScale = 1,
threshold = 1
}
};
return new ChildMotion
{
motion = motion,
directBlendParameter = prop,
motion = bufferBlendTree,
directBlendParameter = MergeBlendTreePass.ALWAYS_ONE,
timeScale = 1
};
}