69 lines
3.1 KiB
C#
69 lines
3.1 KiB
C#
|
|
// WL789_Import.cs — Knight 공격 FBX 의 Root Motion Node 를 <None> 으로 (에디트 모드 · 메타 백업 후)
|
||
|
|
// unity command run_script --file AgentScripts/WL789_Import.cs --entry WL789_Import.Show
|
||
|
|
// unity command run_script --file AgentScripts/WL789_Import.cs --entry WL789_Import.SetMotionNodeNone
|
||
|
|
// unity command run_script --file AgentScripts/WL789_Import.cs --entry WL789_Import.Restore (백업 메타 복원)
|
||
|
|
// 근거: 런타임 실측(2026-09-07 00:3x) — applyRootMotion=true 인데도 Knight@Attack1~3_S 클립의 animator.deltaPosition 합 = 0.000 m
|
||
|
|
// (Chase_Start 1.996 m · Run 0.124 m 는 정상). 클립에 MotionT 커브(hasMotionCurves=True)가 있어 Unity 가 RootT 대신
|
||
|
|
// 움직이지 않는 모션 노드 커브를 루트모션으로 쓰기 때문 → 모션 노드를 None 으로 두면 RootT(실측 0.30 m 등)를 쓴다.
|
||
|
|
using System.IO;
|
||
|
|
using System.Text;
|
||
|
|
using UnityEditor;
|
||
|
|
using UnityEngine;
|
||
|
|
|
||
|
|
public static class WL789_Import
|
||
|
|
{
|
||
|
|
static readonly string[] Paths =
|
||
|
|
{
|
||
|
|
"Assets/Res_Addr/Animations/Animation/OneHand/Knight@Attack1_S.FBX",
|
||
|
|
"Assets/Res_Addr/Animations/Animation/OneHand/Knight@Attack2_S.FBX",
|
||
|
|
"Assets/Res_Addr/Animations/Animation/OneHand/Knight@Attack3_S.FBX",
|
||
|
|
};
|
||
|
|
const string BackupDir = "AgentScripts/staging/_backup_wl789_meta";
|
||
|
|
|
||
|
|
public static object Show()
|
||
|
|
{
|
||
|
|
var sb = new StringBuilder();
|
||
|
|
foreach (var p in Paths)
|
||
|
|
{
|
||
|
|
var imp = AssetImporter.GetAtPath(p) as ModelImporter;
|
||
|
|
sb.AppendLine(Path.GetFileName(p) + " motionNodeName='" + (imp != null ? imp.motionNodeName : "?") + "' animationType=" + (imp != null ? imp.animationType.ToString() : "?"));
|
||
|
|
}
|
||
|
|
return sb.ToString();
|
||
|
|
}
|
||
|
|
|
||
|
|
public static object SetMotionNodeNone()
|
||
|
|
{
|
||
|
|
if (EditorApplication.isPlaying) return "ABORT: Play 중";
|
||
|
|
Directory.CreateDirectory(BackupDir);
|
||
|
|
var sb = new StringBuilder();
|
||
|
|
foreach (var p in Paths)
|
||
|
|
{
|
||
|
|
var meta = p + ".meta";
|
||
|
|
File.Copy(meta, Path.Combine(BackupDir, Path.GetFileName(meta)), true);
|
||
|
|
var imp = AssetImporter.GetAtPath(p) as ModelImporter;
|
||
|
|
if (imp == null) { sb.AppendLine(p + " importer null"); continue; }
|
||
|
|
string before = imp.motionNodeName;
|
||
|
|
imp.motionNodeName = "";
|
||
|
|
imp.SaveAndReimport();
|
||
|
|
var imp2 = AssetImporter.GetAtPath(p) as ModelImporter;
|
||
|
|
sb.AppendLine(Path.GetFileName(p) + " motionNode '" + before + "' → '" + (imp2 != null ? imp2.motionNodeName : "?") + "'");
|
||
|
|
}
|
||
|
|
AssetDatabase.SaveAssets();
|
||
|
|
return sb.ToString();
|
||
|
|
}
|
||
|
|
|
||
|
|
public static object Restore()
|
||
|
|
{
|
||
|
|
if (EditorApplication.isPlaying) return "ABORT: Play 중";
|
||
|
|
int n = 0;
|
||
|
|
foreach (var p in Paths)
|
||
|
|
{
|
||
|
|
var b = Path.Combine(BackupDir, Path.GetFileName(p) + ".meta");
|
||
|
|
if (!File.Exists(b)) continue;
|
||
|
|
File.Copy(b, p + ".meta", true); n++;
|
||
|
|
AssetDatabase.ImportAsset(p, ImportAssetOptions.ForceUpdate);
|
||
|
|
}
|
||
|
|
return "restored " + n + " meta(s)";
|
||
|
|
}
|
||
|
|
}
|