ThreeKingdomsSlingshot/Tools/make_ib_fx_copies.cs

156 lines
8.2 KiB
C#
Raw Permalink Normal View History

스킬 이펙트 1차 + IB(쿠로네코) 연출 시험 — 돌진·조준 UI·타격감 (PD 2026-11-10) - 기본 공격(돌진) = IB 이펙트 그대로 시험: 앞 빛 물결 · 속도 꼬리(진영색 4색 · 멈춘 자리에서 0.12초 흐려짐) · WL 흙먼지 · 기준점 dash(아래로 갈수록 발 쪽) · 히트 이펙트 제거(PD 지정 대기) - 슬링샷 방향 결정 UI = IB GameTouchArrow 이식(IbAimArrow · IB 유닛 반지름 0.496 기준 비율) + 진행 중 캐릭터 연출(IbUnitMarks: 발밑 원 · 몸 빛 · 조준 중 속성 방울) · 값 표 Resources/Skills/ib_ui.csv - 기병: 복귀 영역(채운 원 · PreviewCavalryReturn) · 복귀 때 돌아서기(UnitView.TurnAround) - 타격감: HitFeel + CameraController.Shake · 표 hit_feel.csv(IB 흔들림 값은 디컴파일에 없어 추정값) - 액티브 스킬 1차 연출(Fable 제안 56 스킬 · 사본 Resources/Fx/TKS_Fx_Sk_*) · SkillVfx 확장(s_camp · f_fwd · f_drift · f_fade · s_over · b_flat · 트레일 페이드) · 셀화 셰이더 포트 - 2D 돌진 시험본(Dash2D · Aura2D test_aura) · 이전 시험 행은 skill_vfx.csv 에 # 주석 - 여포 크기: dz_boss_lvbu 몸 높이 819 → 718(깃털 제외 · 말 탄 유닛 머리 끝 상한 때문에 작아졌음) - 원본 = Assets/VFX/IB(쿠로네코 · GUID 유지 · Tools/wl_vfx_import.py --skip-scripts) · 사본 도구 Tools/make_ib_fx_copies.cs · make_ib_camp_textures.py · build_dash2d.cs - 테스트 PlayMode 118/118 통과 · 자동 재직렬화(png meta · UITheme · ProjectSettings) 제외 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-10 04:19:44 +00:00
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;
using UnityEngine.SceneManagement;
// IB(쿠로네코) 이펙트 → 게임이 읽는 사본 Resources/Fx/TKS_Fx_IB_*(PD 2026-11-10 「IB 이펙트를 그대로 써서 확인 → 나중에 구조에 맞게 새로 그림(화풍 통일)」).
// 원본 = Tools/wl_vfx_import.py copy … --wl E:/NerdNavis/Kuroneko/KuronekoClient --dest Assets/VFX/IB --skip-scripts 로 옮긴 Assets/VFX/IB/AssetResources/FX/*.prefab(무수정).
// 사본 = IB 전용 스크립트 부품(VisualEffectData 등 · 이 게임에 없음) 제거 · 방향 있는 것은 감싸는 루트를 두고 안쪽을 Z −90°
// (IB 정면 = +Y · FollowUnit = FromToRotation(up, 진행 방향) → 이 게임 b_flat 정면 = +X 에 맞춤).
// 실행: unity command --project-path "E:/NerdNavis/ThreeKingdomsSlingshot" script eval --file Tools/make_ib_fx_copies.cs
string src = "Assets/VFX/IB/AssetResources/";
string dst = "Assets/Resources/Fx/";
// { IB 경로(AssetResources 아래), 사본 이름, 1 = 진행 방향으로 돌림(감싸는 루트) }
var jobs = new[]
{
new[] { "FX/ef_booster", "TKS_Fx_IB_Booster", "1" },
new[] { "FX/ef_speed_tail", "TKS_Fx_IB_SpeedTail", "1" },
new[] { "FX/ef_booster_dust", "TKS_Fx_IB_BoosterDust", "1" },
new[] { "FX/ef_normal_hit", "TKS_Fx_IB_NormalHit", "0" },
new[] { "FX/ef_bounce_hit", "TKS_Fx_IB_BounceHit", "0" },
new[] { "FX/ef_dust", "TKS_Fx_IB_Dust", "0" },
// 방향 결정 UI(PD 2026-11-10 「IB 와 같이 슬링샷 조작 시 방향 결정 UI 등을 그대로 이식」) — 동작은 TKS.IbAimArrow(IB GameTouchArrow 이식)
new[] { "Game/GameArrow", "TKS_Fx_IB_GameArrow", "0" },
// 슬링샷 진행 중 캐릭터 연출(PD 2026-11-10 「선택된 캐릭터 주위 연출 누락」) — IB ShowUserTurnMark(발밑 도는 원 · 몸 둘레 빛) · 조준 중 모든 유닛 속성 방울(SetActiveBarrierVisualEffect)
new[] { "FX/ef_target_circle", "TKS_Fx_IB_TargetCircle", "0" },
new[] { "FX/ef_attack_ready_standard", "TKS_Fx_IB_AttackReady", "0" },
new[] { "FX/ef_attribute_water", "TKS_Fx_IB_Attribute_water", "0" },
new[] { "FX/ef_attribute_tree", "TKS_Fx_IB_Attribute_tree", "0" },
new[] { "FX/ef_attribute_fire", "TKS_Fx_IB_Attribute_fire", "0" },
new[] { "FX/ef_attribute_dark", "TKS_Fx_IB_Attribute_dark", "0" },
new[] { "FX/ef_attribute_glow", "TKS_Fx_IB_Attribute_glow", "0" },
};
AssetDatabase.Refresh();
var sb = new System.Text.StringBuilder();
var scene = EditorSceneManager.NewPreviewScene();
foreach (var j in jobs)
{
var prefab = AssetDatabase.LoadAssetAtPath<GameObject>(src + j[0] + ".prefab");
if (prefab == null) { sb.AppendLine("없음 " + j[0]); continue; }
var inst = (GameObject)PrefabUtility.InstantiatePrefab(prefab, scene);
PrefabUtility.UnpackPrefabInstance(inst, PrefabUnpackMode.Completely, InteractionMode.AutomatedAction);
int removed = 0;
foreach (var t in inst.GetComponentsInChildren<Transform>(true)) removed += GameObjectUtility.RemoveMonoBehavioursWithMissingScript(t.gameObject);
foreach (var r in inst.GetComponentsInChildren<Renderer>(true)) r.sortingLayerID = 0; // IB 정렬 레이어(이 게임에 없음 · <unknown layer>) → Default · 순서는 표 n_order
foreach (var an in inst.GetComponentsInChildren<Animator>(true)) // 클립의 소리 이벤트(FGPlaySoundByString) 받는 곳 — 없으면 재생마다 콘솔 오류
if (an.GetComponent<TKS.IbFxAnimEvents>() == null) an.gameObject.AddComponent<TKS.IbFxAnimEvents>();
GameObject root = inst;
if (j[2] == "1")
{
root = new GameObject(j[1]);
SceneManager.MoveGameObjectToScene(root, scene);
inst.transform.SetParent(root.transform, false);
inst.transform.localPosition = Vector3.zero;
inst.transform.localRotation = Quaternion.Euler(0f, 0f, -90f);
}
else root.name = j[1];
PrefabUtility.SaveAsPrefabAsset(root, dst + j[1] + ".prefab");
Object.DestroyImmediate(root);
var rs = AssetDatabase.LoadAssetAtPath<GameObject>(dst + j[1] + ".prefab").GetComponentsInChildren<Renderer>(true);
var layers = new System.Collections.Generic.HashSet<string>();
foreach (var r in rs) layers.Add(r.sortingLayerName + "/" + r.sortingOrder);
sb.AppendLine(j[1] + " · 스크립트 부품 제거 " + removed + " · 렌더러 " + rs.Length + " · 정렬 " + string.Join(",", layers));
}
EditorSceneManager.ClosePreviewScene(scene);
// ── 진영색 사본(PD 2026-11-10 「진영 색을 입히고」): TKS_Fx_IB_Booster_<진영> · TKS_Fx_IB_SpeedTail_<진영> ──
// 색 = 채도 있는 색만 색상(H)을 진영색으로(채도·밝기 유지 · 흰 심 그대로) · 꼬리 그림 = Tools/make_ib_camp_textures.py 가 만든 Assets/VFX/IB/_TKS/Tail_Basic02_<진영>.png
// 진영색 원본 = Tools/dash2d_camps.csv
Color HueTo(Color c, float hue)
{
float h, s, v;
Color.RGBToHSV(c, out h, out s, out v);
if (s < 0.15f) return c;
var n = Color.HSVToRGB(hue, s, v);
n.a = c.a;
return n;
}
Gradient GradHue(Gradient g, float hue)
{
if (g == null) return null;
var ks = g.colorKeys;
for (int i = 0; i < ks.Length; i++) ks[i].color = HueTo(ks[i].color, hue);
var ng = new Gradient();
ng.SetKeys(ks, g.alphaKeys);
ng.mode = g.mode;
return ng;
}
ParticleSystem.MinMaxGradient MmgHue(ParticleSystem.MinMaxGradient m, float hue)
{
switch (m.mode)
{
case ParticleSystemGradientMode.Color: return new ParticleSystem.MinMaxGradient(HueTo(m.color, hue));
case ParticleSystemGradientMode.TwoColors: return new ParticleSystem.MinMaxGradient(HueTo(m.colorMin, hue), HueTo(m.colorMax, hue));
case ParticleSystemGradientMode.TwoGradients: return new ParticleSystem.MinMaxGradient(GradHue(m.gradientMin, hue), GradHue(m.gradientMax, hue));
default:
var r = new ParticleSystem.MinMaxGradient(GradHue(m.gradient, hue));
r.mode = m.mode;
return r;
}
}
string tks = "Assets/VFX/IB/_TKS/";
var tailMat0 = AssetDatabase.LoadAssetAtPath<Material>("Assets/VFX/IB/FGResources/Effect/Material/Tail_Basic02.mat");
foreach (var line in System.IO.File.ReadAllLines("Tools/dash2d_camps.csv"))
{
var cells = line.Trim('').Split(',');
if (cells.Length < 2 || cells[0] == "s_camp" || cells[0].Length == 0) continue;
string camp = cells[0].Trim();
Color cc;
ColorUtility.TryParseHtmlString(cells[1].Trim(), out cc);
float hue, cs, cv;
Color.RGBToHSV(cc, out hue, out cs, out cv);
var tp = tks + "Tail_Basic02_" + camp + ".png";
var ti = (TextureImporter)AssetImporter.GetAtPath(tp);
ti.wrapMode = TextureWrapMode.Clamp;
ti.mipmapEnabled = false;
ti.alphaIsTransparency = true;
ti.SaveAndReimport();
var mp = tks + "Tail_Basic02_" + camp + ".mat";
var mat = AssetDatabase.LoadAssetAtPath<Material>(mp);
if (mat == null)
{
mat = new Material(tailMat0);
AssetDatabase.CreateAsset(mat, mp);
}
mat.CopyPropertiesFromMaterial(tailMat0);
mat.SetTexture("_MainTex", AssetDatabase.LoadAssetAtPath<Texture2D>(tp));
EditorUtility.SetDirty(mat);
var b = PrefabUtility.LoadPrefabContents(dst + "TKS_Fx_IB_Booster.prefab");
b.name = "TKS_Fx_IB_Booster_" + camp;
foreach (var sr in b.GetComponentsInChildren<SpriteRenderer>(true)) sr.color = HueTo(sr.color, hue);
PrefabUtility.SaveAsPrefabAsset(b, dst + b.name + ".prefab");
PrefabUtility.UnloadPrefabContents(b);
var t = PrefabUtility.LoadPrefabContents(dst + "TKS_Fx_IB_SpeedTail.prefab");
t.name = "TKS_Fx_IB_SpeedTail_" + camp;
foreach (var tr in t.GetComponentsInChildren<TrailRenderer>(true))
{
tr.sharedMaterial = mat;
tr.colorGradient = GradHue(tr.colorGradient, hue);
}
foreach (var ps in t.GetComponentsInChildren<ParticleSystem>(true))
{
var m = ps.main;
m.startColor = MmgHue(m.startColor, hue);
var col = ps.colorOverLifetime;
if (col.enabled) col.color = MmgHue(col.color, hue);
}
PrefabUtility.SaveAsPrefabAsset(t, dst + t.name + ".prefab");
PrefabUtility.UnloadPrefabContents(t);
sb.AppendLine("진영색 " + camp + " " + cells[1].Trim() + " → TKS_Fx_IB_Booster_" + camp + " · TKS_Fx_IB_SpeedTail_" + camp);
}
AssetDatabase.SaveAssets();
return sb.ToString();