Project_WL/AgentScripts/WL814k_Bake.cs

134 lines
7.8 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// WL-814k 베이크 드라이버 (에디트 모드 전용 · 게임 코드 아님)
// 에셋 만들기 : unity command run_script --file AgentScripts/WL814k_Bake.cs --entry WL814k_Bake.MakeAssets
// 시범 2종 굽기: unity command run_script --file AgentScripts/WL814k_Bake.cs --entry WL814k_Bake.BakeDemo
// 임의 프리팹 : WL814k_Bake.Targets 를 바꾸거나 에디터 창(WL ▸ 도트 스프라이트 굽기)을 쓴다.
//
// 🔴 이 드라이버에만 「어떤 프리팹을 구울지」가 적혀 있다. 툴(Assets/WL/Look/Sprite/Editor/WLSpriteBaker.cs)
// 에는 캐릭터 이름이 0개다 — PD 가 캐릭터 에셋을 바꿔도 툴은 그대로 쓴다.
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using UnityEditor;
using UnityEngine;
using WL.Look.SpriteBake;
using WL.Look.SpriteBake.EditorTools;
public static class WL814k_Bake
{
const string kResDir = "Assets/WL/Look/Sprite/Resources/WL";
const string kOutDir = "Assets/WL/Look/Sprite/Baked";
const string kTxt = "AgentScripts/WL814k_BAKE.txt";
// 🔴 1차 시범 = PC 1종 + 잡몹 1종 (전수 전환은 PD 승인 뒤)
// 두 번째 값 = 인게임 실제 루트 스케일(0 이면 프리팹 자체 값).
// PC 는 ClassConfig.f_Scale 0.7 로 스폰된다(814b·발주서 실측) → 그 크기로 구워야
// 스프라이트 1px 이 화면 1px 과 정확히 맞는다. 몹은 프리팹 스케일 그대로(Batty_A = 1.5).
public static readonly string[] Targets = { "Assets/Res_Addr/PC/Ai01.prefab", "Assets/Res_Addr/Mobs/Mob/Batty_A.prefab" };
public static readonly float[] TargetScales = { 0.7f, 0f };
static StringBuilder s_sb;
static void L(string s) { s_sb.AppendLine(s); Debug.Log("[WL814k] " + s); }
// ═════════════════════════════════════════════════════════════════════════
// ① 설정 에셋 2개 만들기
// ═════════════════════════════════════════════════════════════════════════
public static void MakeAssets()
{
s_sb = new StringBuilder();
L("WL-814k 설정 에셋 · " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
Directory.CreateDirectory(kResDir);
Directory.CreateDirectory(kOutDir);
var bake = AssetDatabase.LoadAssetAtPath<WLSpriteBakeSettings>(kResDir + "/WLSpriteBakeSettings.asset");
if (bake == null)
{
bake = ScriptableObject.CreateInstance<WLSpriteBakeSettings>();
AssetDatabase.CreateAsset(bake, kResDir + "/WLSpriteBakeSettings.asset");
L("만듦 " + kResDir + "/WLSpriteBakeSettings.asset");
}
else L("있음 " + kResDir + "/WLSpriteBakeSettings.asset");
var look = AssetDatabase.LoadAssetAtPath<WLSpriteLookSettings>(kResDir + "/WLSpriteLookSettings.asset");
if (look == null)
{
look = ScriptableObject.CreateInstance<WLSpriteLookSettings>();
AssetDatabase.CreateAsset(look, kResDir + "/WLSpriteLookSettings.asset");
L("만듦 " + kResDir + "/WLSpriteLookSettings.asset");
}
else L("있음 " + kResDir + "/WLSpriteLookSettings.asset");
AssetDatabase.SaveAssetIfDirty(bake);
AssetDatabase.SaveAssetIfDirty(look);
WLSpriteBakeSettings.ClearCache();
WLSpriteLookSettings.ClearCache();
L(string.Format("굽기 기본값 — 내림각 {0:0.000}° · 픽셀 {1:0.00000} m · 방향 {2} · 프레임 {3}(자동 {4}) · 팔레트 {5}단계 · 알파컷 {6}",
bake.PitchDeg, bake.WorldPerPixel, bake.dirCount, bake.frameSize, bake.autoFrameSize, bake.paletteLevels, bake.alphaCutoff));
File.WriteAllText(kTxt, s_sb.ToString(), new UTF8Encoding(false));
}
// ═════════════════════════════════════════════════════════════════════════
// ② 시범 2종 굽기 + SO 목록 연결
// ═════════════════════════════════════════════════════════════════════════
public static void BakeDemo() { BakeList(Targets, TargetScales); }
public static void BakeList(string[] paths, float[] scales)
{
s_sb = new StringBuilder();
L("WL-814k 굽기 · " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + " · Unity " + Application.unityVersion);
var sets = new List<WLSpriteSet>();
double total = 0;
for (int ti = 0; ti < paths.Length; ti++)
{
var p = paths[ti];
float scale = (scales != null && ti < scales.Length) ? scales[ti] : 0f;
L("");
L("──────── " + p + (scale > 0f ? " (루트 스케일 " + scale + ")" : " (프리팹 스케일 그대로)"));
// 🔴 굽기마다 설정 에셋을 다시 읽는다 — PNG 임포트가 AssetDatabase 를 돌려
// 참조만 들고 있던 SO 가 언로드돼 null 이 되는 것을 실측했다(첫 시도 실패 원인).
var cfg = AssetDatabase.LoadAssetAtPath<WLSpriteBakeSettings>(kResDir + "/WLSpriteBakeSettings.asset");
if (cfg == null) { L("FAIL — 굽기 설정 에셋 없음. MakeAssets 먼저."); break; }
var r = WLSpriteBaker.Bake(p, cfg, kOutDir, null, scale);
total += r.seconds;
L(r.log.ToString().TrimEnd());
foreach (var n in r.notes) L(" · 「미확인/주의」 " + n);
if (!r.ok) { L("FAIL"); continue; }
L(string.Format("OK — 프레임 {0}×{0} px · 방향 {1} · 총 {2}칸 · 시트 {3}×{4} · PNG {5:N0} B ({6:N1} KB) · {7:0.00}초 · 캐릭터 {8:0} px",
r.frameSize, r.dirCount, r.totalFrames, r.sheetW, r.sheetH, r.pngBytes, r.pngBytes / 1024.0, r.seconds, r.charPixelHeight));
L(" PNG = " + r.pngPath);
L(" SO = " + r.setPath);
var set = AssetDatabase.LoadAssetAtPath<WLSpriteSet>(r.setPath);
if (set != null)
{
sets.Add(set);
var sb2 = new StringBuilder();
foreach (var a in set.actions)
sb2.Append(string.Format("{0}(시작 {1}·{2}프레임·{3:0.0}fps·상태 [{4}]·클립 {5}) ",
a.key, a.startIndex, a.frameCount, a.fps, string.Join("/", a.stateNames), a.clipName));
L(" 동작표 = " + sb2.ToString().TrimEnd());
L(string.Format(" 발밑 픽셀 ({0:0.0}, {1:0.0}) · 픽셀 1개 {2:0.00000} m · 베이크 스케일 {3:0.000}",
set.footPixelX, set.footPixelY, set.worldPerPixel, set.bakeScale));
}
}
// 런타임 SO 에 시트 목록 연결
var look = AssetDatabase.LoadAssetAtPath<WLSpriteLookSettings>(kResDir + "/WLSpriteLookSettings.asset");
if (look != null)
{
look.sets = sets.ToArray();
EditorUtility.SetDirty(look);
AssetDatabase.SaveAssetIfDirty(look);
L("");
L("런타임 SO 연결 — sets " + sets.Count + "개 (" + kResDir + "/WLSpriteLookSettings.asset)");
}
L("");
L(string.Format("합계 굽기 시간 = {0:0.00}초 / {1}종 → 1종당 {2:0.00}초", total, paths.Length, total / Math.Max(1, paths.Length)));
Write();
}
static void Write() { File.WriteAllText(kTxt, s_sb.ToString(), new UTF8Encoding(false)); Debug.Log("[WL814k] → " + kTxt); }
}