// ───────────────────────────────────────────────────────────────────────────── // WL_NolantMerchantSetup.cs — 상인 대역 캐릭터(Stylized NPC - Peasant Nolant · 밀짚모자) WL 프리팹 변형 만들기 (2026-10-15 PD) // // PD 「Stylized NPC - Peasant Nolant 에셋을 추가했어. "상인 설치" 시 방금 추가한 에셋의 밀집모자를 쓴 캐릭터를 가판대 대신 세우고 싶어.」 // ■ 원본 에셋은 고치지 않는다(재질·프리팹·컨트롤러 0줄) — WL 폴더에 새로 만든다. // · 재질: 원본이 Built-in `Standard` 라 URP 에서 분홍 → FI 캐릭터와 같은 `URP/Simple Lit`(+ 원본 텍스처) 복사본 // · 애니메이터: 원본 컨트롤러 기본 상태가 `Walk` + Apply Root Motion = 제자리에서 걸어 나간다 → 대기(Idle) 1상태 컨트롤러 · 루트 모션 끔 // · 프리팹: 원본 프리팹의 **변형(Variant)** — 위 두 가지만 덮어쓴다 // · 텍스처: Android 최대 1024(모바일 · 원본 2048) — 임포터 플랫폼 덮어쓰기만 // 실행 = unity command run_script --file AgentScripts/WL_NolantMerchantSetup.cs --entry WL_NolantMerchantSetup.Run --args "[\"Yellow\"]" // ───────────────────────────────────────────────────────────────────────────── using System.IO; using UnityEditor; using UnityEditor.Animations; using UnityEngine; public static class WL_NolantMerchantSetup { const string SrcRoot = "Assets/Stylized NPC - Peasant Nolant"; const string OutDir = "Assets/WL/Island/NPC"; public static string Run(string color) { if (string.IsNullOrEmpty(color)) color = "Yellow"; string srcPrefab = SrcRoot + "/Prefabs/Peasant Nolant " + color + "(Free Version).prefab"; string srcTex = SrcRoot + "/Textures/Peasant Nolant " + color + ".png"; string fbx = SrcRoot + "/Models/Peasant Nolant(Free Version).fbx"; var prefab = AssetDatabase.LoadAssetAtPath(srcPrefab); var tex = AssetDatabase.LoadAssetAtPath(srcTex); if (prefab == null || tex == null) return "원본 없음 — " + srcPrefab + " / " + srcTex; if (!AssetDatabase.IsValidFolder(OutDir)) { Directory.CreateDirectory(OutDir); AssetDatabase.Refresh(); } // ① 텍스처 — Android 최대 1024 var ti = AssetImporter.GetAtPath(srcTex) as TextureImporter; var ps = ti.GetPlatformTextureSettings("Android"); if (!ps.overridden || ps.maxTextureSize != 1024) { ps.overridden = true; ps.maxTextureSize = 1024; ps.format = TextureImporterFormat.ASTC_6x6; ti.SetPlatformTextureSettings(ps); ti.SaveAndReimport(); } // ② 재질 — URP Simple Lit + 원본 텍스처(FI 캐릭터 Skin 재질과 같은 셰이더 · 반사광 없음 = 원본 Standard 광택 0 과 같은 무광) string matPath = OutDir + "/WL_Nolant_" + color + ".mat"; var mat = AssetDatabase.LoadAssetAtPath(matPath); if (mat == null) { mat = new Material(Shader.Find("Universal Render Pipeline/Simple Lit")); AssetDatabase.CreateAsset(mat, matPath); } mat.shader = Shader.Find("Universal Render Pipeline/Simple Lit"); mat.SetTexture("_BaseMap", tex); mat.SetColor("_BaseColor", Color.white); mat.SetFloat("_Smoothness", 0f); mat.SetFloat("_SpecularHighlights", 0f); mat.DisableKeyword("_SPECULAR_COLOR"); mat.DisableKeyword("_SPECGLOSSMAP"); mat.enableInstancing = true; EditorUtility.SetDirty(mat); // ③ 대기 1상태 컨트롤러 string ctrlPath = OutDir + "/WL_Nolant_Idle.controller"; AnimationClip idle = null; foreach (var o in AssetDatabase.LoadAllAssetsAtPath(fbx)) if (o is AnimationClip c && !c.name.StartsWith("__") && c.name.EndsWith("Idle")) idle = c; if (idle == null) return "Idle 클립 없음 — " + fbx; var ctrl = AssetDatabase.LoadAssetAtPath(ctrlPath); if (ctrl == null) ctrl = UnityEditor.Animations.AnimatorController.CreateAnimatorControllerAtPath(ctrlPath); var sm = ctrl.layers[0].stateMachine; foreach (var st in sm.states) sm.RemoveState(st.state); var s = sm.AddState("Idle"); s.motion = idle; sm.defaultState = s; EditorUtility.SetDirty(ctrl); // ④ 프리팹 변형 — 재질 · 컨트롤러 · 루트 모션 끔 string varPath = OutDir + "/WL_Merchant_Nolant_" + color + ".prefab"; var inst = (GameObject)PrefabUtility.InstantiatePrefab(prefab); int mats = 0; foreach (var r in inst.GetComponentsInChildren(true)) { var arr = r.sharedMaterials; for (int i = 0; i < arr.Length; i++) { arr[i] = mat; mats++; } r.sharedMaterials = arr; r.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.On; } var an = inst.GetComponent(); an.runtimeAnimatorController = ctrl; an.applyRootMotion = false; an.cullingMode = AnimatorCullingMode.CullUpdateTransforms; var saved = PrefabUtility.SaveAsPrefabAsset(inst, varPath); Object.DestroyImmediate(inst); AssetDatabase.SaveAssets(); return "OK — " + varPath + " (원본 " + srcPrefab + " 변형 · 재질 " + mats + "칸 → " + matPath + " · 컨트롤러 " + ctrlPath + " = " + idle.name + " · 루트 모션 끔 · 텍스처 Android 1024/ASTC6x6) · saved=" + (saved != null) + " · variant=" + (saved != null && PrefabUtility.GetPrefabAssetType(saved) == PrefabAssetType.Variant); } }