Files

62 lines
2.7 KiB
C#

#if UNITY_EDITOR
using System.Linq;
using System.Text;
using UnityEditor;
using UnityEngine;
public static class MeasureClipMotion
{
public static string Run()
{
var sb = new StringBuilder();
foreach (var name in new[] { "Idle", "Walk", "Attack" })
{
var clip = AssetDatabase.LoadAssetAtPath<AnimationClip>($"Assets/Bundles/Characters/Animal/RockBall/Clips/{name}.anim");
if (clip == null) { sb.AppendLine(name + " missing"); continue; }
var binds = AnimationUtility.GetCurveBindings(clip);
float maxRange = 0f;
string maxBind = "";
int moving = 0;
foreach (var b in binds)
{
var c = AnimationUtility.GetEditorCurve(clip, b);
if (c == null || c.keys.Length == 0) continue;
float mn = float.MaxValue, mx = float.MinValue;
foreach (var k in c.keys) { if (k.value < mn) mn = k.value; if (k.value > mx) mx = k.value; }
// also sample densely
for (float t = 0; t <= clip.length; t += clip.length / 20f)
{
float v = c.Evaluate(t);
if (v < mn) mn = v; if (v > mx) mx = v;
}
float range = mx - mn;
if (range > 1e-4f) moving++;
if (range > maxRange) { maxRange = range; maxBind = b.path + "/" + b.propertyName; }
}
sb.AppendLine($"{name}: len={clip.length:F3} binds={binds.Length} movingCurves={moving} maxRange={maxRange:F5} at {maxBind}");
}
// Compare bone rest vs sampled pose at mid Walk on instantiated prefab
var prefab = AssetDatabase.LoadAssetAtPath<GameObject>("Assets/Bundles/Characters/Animal/RockBall/RockBall_Rigged.prefab");
var go = (GameObject)PrefabUtility.InstantiatePrefab(prefab);
var anim = go.GetComponentInChildren<Animator>();
anim.SetInteger("Motion", 1);
anim.Update(0f);
// record bone rotations at t=0 and after scrubbing
var bones = go.GetComponentsInChildren<Transform>().Where(t => t.name.StartsWith("bone_")).ToArray();
var r0 = bones.Select(b => b.localRotation).ToArray();
for (int i = 0; i < 30; i++) anim.Update(0.05f);
float maxAng = 0f;
string which = "";
for (int i = 0; i < bones.Length; i++)
{
float ang = Quaternion.Angle(r0[i], bones[i].localRotation);
if (ang > maxAng) { maxAng = ang; which = bones[i].name; }
}
sb.AppendLine($"prefab Walk scrub 1.5s maxBoneDeltaDeg={maxAng:F2} bone={which}");
Object.DestroyImmediate(go);
return sb.ToString();
}
}
#endif