62 lines
2.7 KiB
C#
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
|