Project_WL/AgentScripts/WL814k_Survey3.cs

88 lines
3.7 KiB
C#

// WL-814k 실측 조사 ③ — Humanoid/Generic 샘플링 경로 확정 (읽기만)
// run: unity command run_script --file AgentScripts/WL814k_Survey3.cs --entry WL814k_Survey3.Run
using System;
using System.IO;
using System.Text;
using UnityEditor;
using UnityEngine;
public static class WL814k_Survey3
{
const string kTxt = "AgentScripts/WL814k_SURVEY3.txt";
static StringBuilder s_sb;
static void L(string s) { s_sb.AppendLine(s); Debug.Log("[WL814k] " + s); }
public static void Run()
{
s_sb = new StringBuilder();
L("WL-814k 실측 ③ 샘플링 · " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
try
{
Test("Assets/Res_Addr/PC/Ai01.prefab", new[] { "Idle", "Run", "Atk2_wing", "LightHit", "death_F3441" });
Test("Assets/Res_Addr/Mobs/Mob/Batty_A.prefab", new[] { "Idle", "Move", "Attack", "Damage", "Die" });
}
catch (Exception ex) { L("EXCEPTION " + ex); }
finally { if (AnimationMode.InAnimationMode()) AnimationMode.StopAnimationMode(); }
File.WriteAllText(kTxt, s_sb.ToString(), new UTF8Encoding(false));
Debug.Log("[WL814k] → " + kTxt);
}
static void Test(string prefab, string[] clipNames)
{
L("");
L("== " + prefab + " ==");
var src = AssetDatabase.LoadAssetAtPath<GameObject>(prefab);
var inst = (GameObject)PrefabUtility.InstantiatePrefab(src);
inst.transform.position = Vector3.zero; inst.transform.rotation = Quaternion.identity;
try
{
var anim = inst.GetComponentInChildren<Animator>(true);
var rac = anim.runtimeAnimatorController;
foreach (var name in clipNames)
{
AnimationClip clip = null;
foreach (var c in rac.animationClips) if (c.name == name) { clip = c; break; }
if (clip == null) { L(" " + name + " → 클립 없음"); continue; }
// ⓐ AnimationMode 경로
float aSpread = Spread(inst, clip, true);
// ⓑ clip.SampleAnimation 경로
float bSpread = Spread(inst, clip, false);
L(string.Format(" {0,-14} len {1,5:0.00}s · AnimationMode Δbounds {2:0.0000} m · SampleAnimation Δbounds {3:0.0000} m",
name, clip.length, aSpread, bSpread));
}
}
finally { if (AnimationMode.InAnimationMode()) AnimationMode.StopAnimationMode(); UnityEngine.Object.DestroyImmediate(inst); }
}
// 클립을 8등분해 찍고, 전체 렌더러 바운드 중심의 최대 이동량(= 실제로 포즈가 바뀌었는가)
static float Spread(GameObject inst, AnimationClip clip, bool useAnimationMode)
{
var rs = inst.GetComponentsInChildren<SkinnedMeshRenderer>(true);
Vector3 min = Vector3.positiveInfinity, max = Vector3.negativeInfinity;
for (int i = 0; i < 8; i++)
{
float t = clip.length * i / 8f;
if (useAnimationMode)
{
AnimationMode.StartAnimationMode();
AnimationMode.BeginSampling();
AnimationMode.SampleAnimationClip(inst, clip, t);
AnimationMode.EndSampling();
AnimationMode.StopAnimationMode();
}
else
{
clip.SampleAnimation(inst, t);
}
Bounds b = new Bounds(); bool any = false;
foreach (var r in rs) { if (!any) { b = r.bounds; any = true; } else b.Encapsulate(r.bounds); }
if (!any) continue;
min = Vector3.Min(min, b.min); max = Vector3.Max(max, b.max);
}
if (float.IsInfinity(min.x)) return -1f;
return (max - min).magnitude;
}
}