Project_WL/AgentScripts/WL825_SpearSetup.cs

84 lines
4.3 KiB
C#

// WL825_SpearSetup.cs — 창 계열 자산 조립 (에디터 · 1회) (#825 · 2026-10-09 · PD 「창을 넣어서 6종」)
// ① 한손검 컨트롤러 복제 → pcanim_spear.controller · 공격 3상태(attack/Attack2/Attack3)의 모션을 Shinabro 창 클립으로 교체
// ② PurePoly 창 모델 → Assets/Res_Addr/Weapon/PP_Theme_01_Spear_001.prefab (Make_Weapon 이 이 경로를 Addressables 로 읽는다)
// ③ 두 자산을 Addressables 에 등록(주소 = 경로 · 한손검 컨트롤러와 같은 그룹)
// 실행: unity command run_script --file AgentScripts/WL825_SpearSetup.cs --entry WL825_SpearSetup.Run --timeout 120
using System.Text;
using UnityEditor;
using UnityEditor.Animations;
using UnityEditor.AddressableAssets;
using UnityEditor.AddressableAssets.Settings;
using UnityEngine;
public static class WL825_SpearSetup
{
const string SrcCtrl = "Assets/Res_Addr/Animations/pcanim_onehand.controller";
const string DstCtrl = "Assets/Res_Addr/Animations/pcanim_spear.controller";
const string ClipDir = "Assets/Shinabro/Platform_Animation/Animation/07_Spear/";
const string SrcFbx = "Assets/ResWork/PurePoly/Fantasy RPG Weapons/Meshes/PP_Theme_01_Spear_001.fbx";
const string DstPrefab = "Assets/Res_Addr/Weapon/PP_Theme_01_Spear_001.prefab";
static AnimationClip LoadClip(string fbx)
{
foreach (var o in AssetDatabase.LoadAllAssetsAtPath(fbx))
{
var c = o as AnimationClip;
if (c != null && !c.name.StartsWith("__preview__")) return c;
}
return null;
}
public static string Run()
{
var sb = new StringBuilder();
// ① 컨트롤러
if (AssetDatabase.LoadAssetAtPath<UnityEditor.Animations.AnimatorController>(DstCtrl) == null)
{
if (!AssetDatabase.CopyAsset(SrcCtrl, DstCtrl)) return "컨트롤러 복제 실패 " + SrcCtrl;
sb.Append("컨트롤러 복제 · ");
}
var ctrl = AssetDatabase.LoadAssetAtPath<UnityEditor.Animations.AnimatorController>(DstCtrl);
if (ctrl == null) return "컨트롤러 로드 실패";
var map = new[] { new[] { "attack", "Stander@Spear_Attack1.FBX" }, new[] { "Attack2", "Stander@Spear_Attack2.FBX" }, new[] { "Attack3", "Stander@Spear_Attack3.FBX" } };
int swapped = 0;
var sm = ctrl.layers[0].stateMachine;
foreach (var pair in map)
{
var clip = LoadClip(ClipDir + pair[1]);
if (clip == null) { sb.Append("클립 없음 ").Append(pair[1]).Append(" · "); continue; }
foreach (var cs in sm.states)
if (cs.state.name == pair[0]) { cs.state.motion = clip; swapped++; sb.Append(pair[0]).Append('→').Append(clip.name).Append('(').Append(clip.length.ToString("0.00")).Append("s) · "); }
}
EditorUtility.SetDirty(ctrl);
// ② 무기 프리팹
if (AssetDatabase.LoadAssetAtPath<GameObject>(DstPrefab) == null)
{
var fbx = AssetDatabase.LoadAssetAtPath<GameObject>(SrcFbx);
if (fbx == null) return sb + "창 모델 없음 " + SrcFbx;
var inst = (GameObject)PrefabUtility.InstantiatePrefab(fbx);
inst.name = "PP_Theme_01_Spear_001";
PrefabUtility.SaveAsPrefabAsset(inst, DstPrefab);
Object.DestroyImmediate(inst);
sb.Append("무기 프리팹 생성 · ");
}
// ③ Addressables
var settings = AddressableAssetSettingsDefaultObject.Settings;
if (settings == null) sb.Append("Addressables 설정 없음(등록 생략) · ");
else
{
var srcEntry = settings.FindAssetEntry(AssetDatabase.AssetPathToGUID(SrcCtrl));
var group = srcEntry != null ? srcEntry.parentGroup : settings.DefaultGroup;
foreach (var p in new[] { DstCtrl, DstPrefab })
{
var guid = AssetDatabase.AssetPathToGUID(p);
var e = settings.CreateOrMoveEntry(guid, group, false, false);
e.address = p;
sb.Append("주소 ").Append(p).Append(" @").Append(group.Name).Append(" · ");
}
settings.SetDirty(AddressableAssetSettings.ModificationEvent.EntryMoved, null, true, true);
}
AssetDatabase.SaveAssets();
return sb + "교체 " + swapped + "/3";
}
}