135 lines
8.1 KiB
C#
135 lines
8.1 KiB
C#
// WL789_Diag.cs — OnAnimatorMove 호출 여부 · CanAttackStep 판정 · Animator 위치 진단 (Play 전용)
|
|
// unity command run_script --file AgentScripts/WL789_Diag.cs --entry WL789_Diag.Run --args '[6.0]'
|
|
// unity command run_script --file AgentScripts/WL789_Diag.cs --entry WL789_Diag.Report
|
|
using System.Collections;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using UnityEngine;
|
|
|
|
public static class WL789_Diag
|
|
{
|
|
const string Out = "Screenshots_WL/combat5/p_wl789_diag.txt";
|
|
|
|
class RmProbe : MonoBehaviour
|
|
{
|
|
public int calls; public float rawAccum; public int nonZero;
|
|
void OnAnimatorMove()
|
|
{
|
|
calls++;
|
|
var a = GetComponent<Animator>();
|
|
if (a != null) { var d = a.deltaPosition; d.y = 0f; rawAccum += d.magnitude; if (d.sqrMagnitude > 1e-10f) nonZero++; }
|
|
}
|
|
}
|
|
|
|
class Host : MonoBehaviour
|
|
{
|
|
public IEnumerator Co(float seconds)
|
|
{
|
|
var sb = new StringBuilder();
|
|
var me = Object.FindObjectsByType<MyActor>(FindObjectsInactive.Exclude, FindObjectsSortMode.None).FirstOrDefault() as PCActor;
|
|
if (me == null) { Done(sb.AppendLine("PCActor none (MyActor 가 PCActor 가 아님)")); yield break; }
|
|
var anim = me.m_animation;
|
|
sb.AppendLine("animator=" + (anim != null ? anim.name : "null") + " sameGO=" + (anim != null && anim.gameObject == me.gameObject) + " applyRootMotion=" + (anim != null ? anim.applyRootMotion.ToString() : "?")
|
|
+ " comps=" + (anim != null ? string.Join(",", anim.GetComponents<MonoBehaviour>().Select(c => c.GetType().Name)) : "-"));
|
|
var probe = anim.gameObject.AddComponent<RmProbe>();
|
|
int canTrue = 0, frames = 0; string anims = ""; string lastA = "";
|
|
float t0 = Time.time;
|
|
while (Time.time - t0 < seconds)
|
|
{
|
|
frames++;
|
|
if (me.WL_CanAttackStep()) canTrue++;
|
|
string a = me.Get_CurAnim().ToString();
|
|
if (a != lastA) { anims += a + "(" + (Time.time - t0).ToString("F1") + ") "; lastA = a; }
|
|
yield return null;
|
|
}
|
|
sb.AppendLine("frames=" + frames + " canAttackStepTrue=" + canTrue + " rmProbe.calls=" + probe.calls + " nonZeroDelta=" + probe.nonZero + " rawAccum=" + probe.rawAccum.ToString("F2") + " m");
|
|
sb.AppendLine("curAnim seq: " + anims);
|
|
sb.AppendLine("AttackRootMotion apply=" + WL.Combat.AttackRootMotion.ApplyCount + " raw=" + WL.Combat.AttackRootMotion.RawAccum.ToString("F2"));
|
|
Destroy(probe);
|
|
Done(sb);
|
|
}
|
|
void Done(StringBuilder sb) { System.IO.File.WriteAllText(Out, sb.ToString()); Destroy(gameObject); }
|
|
}
|
|
|
|
public static object Run(float seconds)
|
|
{
|
|
if (!Application.isPlaying) return "not playing";
|
|
var h = new GameObject("__wl789diag").AddComponent<Host>();
|
|
h.StartCoroutine(h.Co(seconds));
|
|
return "started";
|
|
}
|
|
public static object Report() { return System.IO.File.Exists(Out) ? System.IO.File.ReadAllText(Out) : "(none)"; }
|
|
|
|
/// <summary>AttackRootMotion 의 private 필드와 각 게이트 판정값을 리플렉션으로 읽는다.</summary>
|
|
public static object Fields()
|
|
{
|
|
if (!Application.isPlaying) return "not playing";
|
|
var me = Object.FindObjectsByType<MyActor>(FindObjectsInactive.Exclude, FindObjectsSortMode.None).FirstOrDefault() as PCActor;
|
|
if (me == null) return "PCActor none";
|
|
var rm = me.m_animation != null ? me.m_animation.GetComponent<WL.Combat.AttackRootMotion>() : null;
|
|
if (rm == null) return "AttackRootMotion none";
|
|
var bf = System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance;
|
|
var t = typeof(WL.Combat.AttackRootMotion);
|
|
var pc = t.GetField("_pc", bf).GetValue(rm) as PCActor;
|
|
var an = t.GetField("_anim", bf).GetValue(rm) as Animator;
|
|
var ag = t.GetField("_agent", bf).GetValue(rm) as UnityEngine.AI.NavMeshAgent;
|
|
var cfg = t.GetField("_cfg", bf).GetValue(rm) as WL.Combat.WLCombatMotionSettings;
|
|
var sb = new StringBuilder();
|
|
sb.AppendLine("_pc=" + (pc != null ? pc.name : "NULL") + " _anim=" + (an != null ? an.name : "NULL") + " _agent=" + (ag != null ? ag.name + " enabled=" + ag.enabled + " onMesh=" + ag.isOnNavMesh : "NULL") + " _cfg=" + (cfg != null ? cfg.attackMoveMode.ToString() : "NULL"));
|
|
sb.AppendLine("canAttackStep(now)=" + me.WL_CanAttackStep() + " dashing=" + WL.Combat.DashDriver.IsDashingNow(me) + " curAnim=" + me.Get_CurAnim() + " enabled=" + rm.enabled + " isActive=" + rm.isActiveAndEnabled);
|
|
sb.AppendLine("statics apply=" + WL.Combat.AttackRootMotion.ApplyCount + " raw=" + WL.Combat.AttackRootMotion.RawAccum);
|
|
return sb.ToString();
|
|
}
|
|
|
|
class ClipDeltaProbe : MonoBehaviour
|
|
{
|
|
public System.Collections.Generic.Dictionary<string, float> sum = new System.Collections.Generic.Dictionary<string, float>();
|
|
public System.Collections.Generic.Dictionary<string, int> frames = new System.Collections.Generic.Dictionary<string, int>();
|
|
public Vector3 posAccum; public float maxDelta;
|
|
void OnAnimatorMove()
|
|
{
|
|
var a = GetComponent<Animator>(); if (a == null) return;
|
|
string clip = "(none)"; var ci = a.GetCurrentAnimatorClipInfo(0); if (ci.Length > 0) clip = ci[0].clip.name;
|
|
var d = a.deltaPosition; d.y = 0f;
|
|
if (!sum.ContainsKey(clip)) { sum[clip] = 0f; frames[clip] = 0; }
|
|
sum[clip] += d.magnitude; frames[clip]++; maxDelta = Mathf.Max(maxDelta, d.magnitude);
|
|
}
|
|
}
|
|
|
|
/// <summary>applyRootMotion 을 지정 상태로 두고 클립별 deltaPosition 합을 잰다(attackMoveMode 는 FixedStep 으로 잠시 바꿔 AttackRootMotion 이 플래그를 건드리지 않게).</summary>
|
|
public static object ClipDelta(int flagOn, float seconds)
|
|
{
|
|
if (!Application.isPlaying) return "not playing";
|
|
var me = Object.FindObjectsByType<MyActor>(FindObjectsInactive.Exclude, FindObjectsSortMode.None).FirstOrDefault() as PCActor;
|
|
if (me == null || me.m_animation == null) return "none";
|
|
var cfg = WL.Combat.WLCombatMotionSettings.Instance; if (cfg != null) cfg.attackMoveMode = WL.Combat.AttackMoveMode.FixedStep;
|
|
me.m_animation.applyRootMotion = flagOn != 0;
|
|
var p = me.m_animation.gameObject.AddComponent<ClipDeltaProbe>();
|
|
var h = new GameObject("__wl789cd").AddComponent<CdHost>(); h.p = p; h.seconds = seconds; h.anim = me.m_animation; h.StartCoroutine(h.Co());
|
|
return "started flag=" + me.m_animation.applyRootMotion + " mode=" + (cfg != null ? cfg.attackMoveMode.ToString() : "?");
|
|
}
|
|
class CdHost : MonoBehaviour
|
|
{
|
|
public ClipDeltaProbe p; public float seconds; public Animator anim;
|
|
public IEnumerator Co()
|
|
{
|
|
yield return new WaitForSeconds(seconds);
|
|
var sb = new StringBuilder("== 클립별 deltaPosition 합 (flag=" + anim.applyRootMotion + ") maxDelta=" + p.maxDelta.ToString("F3") + " ==\n");
|
|
foreach (var k in p.sum.Keys) sb.AppendLine(" " + k + " frames=" + p.frames[k] + " sum=" + p.sum[k].ToString("F3") + " m");
|
|
System.IO.File.WriteAllText("Screenshots_WL/combat5/p_wl789_clipdelta.txt", sb.ToString());
|
|
Destroy(p); Destroy(gameObject);
|
|
}
|
|
}
|
|
public static object ClipDeltaReport() { var f = "Screenshots_WL/combat5/p_wl789_clipdelta.txt"; return System.IO.File.Exists(f) ? System.IO.File.ReadAllText(f) : "(none)"; }
|
|
|
|
/// <summary>applyRootMotion 을 끄고도 deltaPosition 이 계산되는지 본다(끄면 Unity 가 transform 을 직접 옮기지 않는다).</summary>
|
|
public static object RootFlag(int on)
|
|
{
|
|
if (!Application.isPlaying) return "not playing";
|
|
var me = Object.FindObjectsByType<MyActor>(FindObjectsInactive.Exclude, FindObjectsSortMode.None).FirstOrDefault() as PCActor;
|
|
if (me == null || me.m_animation == null) return "none";
|
|
me.m_animation.applyRootMotion = on != 0;
|
|
return "applyRootMotion=" + me.m_animation.applyRootMotion;
|
|
}
|
|
}
|