302 lines
17 KiB
C#
302 lines
17 KiB
C#
|
|
// WL813k_Probe.cs — #813k 레벨업 폭발 검증 프로브 (에디트 모드 전용 · Play 없음 · 에셋 무수정)
|
|||
|
|
//
|
|||
|
|
// unity command run_script --file AgentScripts/WL813k_Probe.cs --entry WL813k_Probe.Run
|
|||
|
|
// 결과: AgentScripts/WL813k_PROBE.txt + Console
|
|||
|
|
//
|
|||
|
|
// 원본·코어·설정 에셋 필드를 수정하지 않는다(런타임 static 스위치와 EffectBudget 카운터만 쓴다).
|
|||
|
|
// 스폰한 이펙트는 DestroyImmediate 로 즉시 정리하고, 씬은 저장하지 않는다.
|
|||
|
|
|
|||
|
|
using System;
|
|||
|
|
using System.IO;
|
|||
|
|
using System.Reflection;
|
|||
|
|
using System.Text;
|
|||
|
|
using UnityEngine;
|
|||
|
|
using WL.Combat.Core;
|
|||
|
|
using WL.Combat.Growth;
|
|||
|
|
|
|||
|
|
public static class WL813k_Probe
|
|||
|
|
{
|
|||
|
|
const string OutPath = "AgentScripts/WL813k_PROBE.txt";
|
|||
|
|
static StringBuilder sb;
|
|||
|
|
|
|||
|
|
public static object Run()
|
|||
|
|
{
|
|||
|
|
sb = new StringBuilder();
|
|||
|
|
L("# WL-813k 레벨업 폭발 프로브 — " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") +
|
|||
|
|
" · Unity " + Application.unityVersion + " · isPlaying=" + Application.isPlaying);
|
|||
|
|
L("");
|
|||
|
|
|
|||
|
|
Section1_Dump();
|
|||
|
|
Section2_Fake();
|
|||
|
|
Section3_BudgetThrottle();
|
|||
|
|
Section4_Recovery();
|
|||
|
|
Section5_Gc();
|
|||
|
|
Section6_Rollback();
|
|||
|
|
Section7_Cleanup();
|
|||
|
|
|
|||
|
|
try { Directory.CreateDirectory("AgentScripts"); File.WriteAllText(OutPath, sb.ToString(), new UTF8Encoding(true)); }
|
|||
|
|
catch (Exception ex) { Debug.LogException(ex); }
|
|||
|
|
Debug.Log(sb.ToString());
|
|||
|
|
return sb.ToString();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
static void L(string s) { sb.AppendLine(s); }
|
|||
|
|
|
|||
|
|
// ── ① 설정 에셋 로드 · 프리팹 실존 ──────────────────────────────────────
|
|||
|
|
static void Section1_Dump()
|
|||
|
|
{
|
|||
|
|
L("## ① 설정 에셋 · 프리팹");
|
|||
|
|
var g = WLGrowthSettings.Instance;
|
|||
|
|
var c = WLCombatCoreSettings.Instance;
|
|||
|
|
L("core asset = " + (c != null ? "found" : "NULL") + " · WLCombatCoreSettings.Enabled = " + WLCombatCoreSettings.Enabled);
|
|||
|
|
L("growth asset= " + (g != null ? "found" : "NULL") + " · WLGrowthSettings.Enabled = " + WLGrowthSettings.Enabled +
|
|||
|
|
" · GrowthEvents.Enabled = " + GrowthEvents.Enabled);
|
|||
|
|
if (g == null) { L("!! 에셋 로드 실패 — 이후 검증 불가"); return; }
|
|||
|
|
L("burstPrefab = " + (g.burstPrefab != null ? g.burstPrefab.name : "NULL") +
|
|||
|
|
" · path = " + (g.burstPrefab != null ? UnityEditor.AssetDatabase.GetAssetPath(g.burstPrefab) : "-"));
|
|||
|
|
if (g.burstPrefab != null)
|
|||
|
|
L(" ParticleSystem = " + g.burstPrefab.GetComponentsInChildren<ParticleSystem>(true).Length +
|
|||
|
|
" · Renderer = " + g.burstPrefab.GetComponentsInChildren<Renderer>(true).Length);
|
|||
|
|
L(JsonUtility.ToJson(g, true));
|
|||
|
|
L("stat 3종 = " + g.statA + " / " + g.statB + " / " + g.statC + " (enum int " + (int)g.statA + "/" + (int)g.statB + "/" + (int)g.statC + ")");
|
|||
|
|
L("EffectBudget.Heavy limit = " + EffectBudget.Limit(EffectBudgetKind.Heavy) + " · count = " + EffectBudget.Count(EffectBudgetKind.Heavy));
|
|||
|
|
L("");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ── ② 가짜 LevelUp 발행 → 이펙트 스폰 ───────────────────────────────────
|
|||
|
|
static void Section2_Fake()
|
|||
|
|
{
|
|||
|
|
L("## ② 가짜 LevelUp 발행 → 이펙트 스폰");
|
|||
|
|
LevelUpBurst.EnsureSubscribed();
|
|||
|
|
GrowthEvents.ResetDiagnostics();
|
|||
|
|
LevelUpBurst.ResetDiagnostics();
|
|||
|
|
L("subscribed = " + LevelUpBurst.Subscribed + " · LevelUp.Count = " + GrowthEvents.LevelUp.Count);
|
|||
|
|
|
|||
|
|
var data = MakeFakeData(6); // Lv 6 → 7 로 오르는 상황
|
|||
|
|
L("fake SD_PC: Lv=" + (int)data.Lv + " · Get_Point()=" + data.Get_Point() + " · Get_UsePoint()=" + data.Get_UsePoint());
|
|||
|
|
|
|||
|
|
GrowthEvents.RaiseLevelUp(data, 7);
|
|||
|
|
|
|||
|
|
L("Raised=" + GrowthEvents.LevelUp.Raised + " Dispatched=" + GrowthEvents.LevelUp.Dispatched +
|
|||
|
|
" TotalRaised=" + GrowthEvents.TotalRaised + " last=" + GrowthEvents.LastEvent);
|
|||
|
|
L("payload: prev→new = " + GrowthEvents.LastPrevLevel + "→" + GrowthEvents.LastLevel +
|
|||
|
|
" · levelsGained=" + GrowthEvents.LastLevelsGained + " · statPointTotal=" + GrowthEvents.LastStatPoint);
|
|||
|
|
L("core forward: CombatEvents.LevelUp.Raised=" + CombatEvents.LevelUp.Raised + " last=" + CombatEvents.LastEvent);
|
|||
|
|
var go = LevelUpBurst.LastBurstInstance;
|
|||
|
|
L("burst instance = " + (go != null ? go.name : "NULL") +
|
|||
|
|
" · pos = " + (go != null ? go.transform.position.ToString("F2") : "-") +
|
|||
|
|
" · 수명(측정) = " + LevelUpBurst.LastLifetime.ToString("F2") + " s");
|
|||
|
|
if (go != null)
|
|||
|
|
L(" 스폰된 ParticleSystem = " + go.GetComponentsInChildren<ParticleSystem>(true).Length +
|
|||
|
|
" · Heavy 슬롯 count = " + EffectBudget.Count(EffectBudgetKind.Heavy));
|
|||
|
|
L("counters: Handled=" + LevelUpBurst.Handled + " BurstSpawned=" + LevelUpBurst.BurstSpawned +
|
|||
|
|
" SkippedBudget=" + LevelUpBurst.SkippedByBudget + " SkippedThrottle=" + LevelUpBurst.SkippedByThrottle +
|
|||
|
|
" SkippedNoPrefab=" + LevelUpBurst.SkippedNoPrefab);
|
|||
|
|
L("HP/MP 전회복: pc=null(에디트 모드 · 월드 PC 없음) → healHp=" + LevelUpBurst.LastHealHp + " healMp=" + LevelUpBurst.LastHealMp +
|
|||
|
|
" (실제 Heal 호출은 Play 필요 — 계산식은 §④에서 검증)");
|
|||
|
|
LevelUpBurst.DespawnLast();
|
|||
|
|
L("정리 후 Heavy count = " + EffectBudget.Count(EffectBudgetKind.Heavy) + " · instance = " + (LevelUpBurst.LastBurstInstance != null));
|
|||
|
|
L("");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ── ③ 상한(EffectBudget) · 연속 레벨업 스로틀 ───────────────────────────
|
|||
|
|
static void Section3_BudgetThrottle()
|
|||
|
|
{
|
|||
|
|
L("## ③ 이펙트 상한 · 연속 레벨업 스로틀");
|
|||
|
|
var g = WLGrowthSettings.Instance;
|
|||
|
|
var data = MakeFakeData(10);
|
|||
|
|
|
|||
|
|
// (a) 상한 초과 = 이펙트만 스킵
|
|||
|
|
LevelUpBurst.ResetDiagnostics();
|
|||
|
|
int limit = EffectBudget.Limit(EffectBudgetKind.Heavy);
|
|||
|
|
int taken = 0;
|
|||
|
|
while (EffectBudget.Count(EffectBudgetKind.Heavy) < limit && taken < 64) { EffectBudget.TryAcquire(EffectBudgetKind.Heavy); taken++; }
|
|||
|
|
L("(a) Heavy 슬롯 선점 " + taken + "/" + limit + " → count=" + EffectBudget.Count(EffectBudgetKind.Heavy));
|
|||
|
|
GrowthEvents.RaiseLevelUp(data, 11);
|
|||
|
|
L(" BurstSpawned=" + LevelUpBurst.BurstSpawned + " SkippedBudget=" + LevelUpBurst.SkippedByBudget +
|
|||
|
|
" Handled=" + LevelUpBurst.Handled + " note=" + LevelUpBurst.LastNote);
|
|||
|
|
for (int i = 0; i < taken; i++) EffectBudget.Release(EffectBudgetKind.Heavy);
|
|||
|
|
L(" 슬롯 반납 후 count=" + EffectBudget.Count(EffectBudgetKind.Heavy));
|
|||
|
|
|
|||
|
|
// (b) 연속 레벨업(같은 프레임 5회) = 이펙트 1회 + 나머지 스로틀
|
|||
|
|
LevelUpBurst.ResetDiagnostics();
|
|||
|
|
GrowthEvents.ResetDiagnostics();
|
|||
|
|
for (int i = 0; i < 5; i++) GrowthEvents.RaiseLevelUp(data, 12 + i);
|
|||
|
|
L("(b) 연속 5회 (interval=" + g.burstMinIntervalSeconds + "s): Handled=" + LevelUpBurst.Handled +
|
|||
|
|
" BurstSpawned=" + LevelUpBurst.BurstSpawned + " SkippedThrottle=" + LevelUpBurst.SkippedByThrottle);
|
|||
|
|
L(" levelsGained(마지막)=" + GrowthEvents.LastLevelsGained + " · Raised=" + GrowthEvents.LevelUp.Raised +
|
|||
|
|
" Dispatched=" + GrowthEvents.LevelUp.Dispatched);
|
|||
|
|
LevelUpBurst.DespawnLast();
|
|||
|
|
L(" 정리 후 Heavy count=" + EffectBudget.Count(EffectBudgetKind.Heavy));
|
|||
|
|
L("");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ── ④ HP/MP 전회복 계산식 ───────────────────────────────────────────────
|
|||
|
|
static void Section4_Recovery()
|
|||
|
|
{
|
|||
|
|
L("## ④ HP/MP 전회복 계산식 (LevelUpBurst.ComputeRecovery · 순수 함수)");
|
|||
|
|
var g = WLGrowthSettings.Instance;
|
|||
|
|
L("설정 비율: hpRecoverRate=" + g.hpRecoverRate + " mpRecoverRate=" + g.mpRecoverRate + " showRecoverHud=" + g.showRecoverHud);
|
|||
|
|
L("| HP/MaxHP | MP/MaxMP | 비율 | healHP | healMP | 결과 HP | 결과 MP |");
|
|||
|
|
Rec(1d, 1000d, 5d, 200d, g.hpRecoverRate, g.mpRecoverRate);
|
|||
|
|
Rec(370d, 1000d, 120d, 200d, g.hpRecoverRate, g.mpRecoverRate);
|
|||
|
|
Rec(1000d, 1000d, 200d, 200d, g.hpRecoverRate, g.mpRecoverRate);
|
|||
|
|
Rec(0d, 1000d, 0d, 200d, g.hpRecoverRate, g.mpRecoverRate);
|
|||
|
|
Rec(370d, 1000d, 120d, 200d, 0.5f, 0.5f);
|
|||
|
|
Rec(370d, 1000d, 120d, 200d, 0f, 0f);
|
|||
|
|
L("");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
static void Rec(double hp, double maxHp, double mp, double maxMp, float hpRate, float mpRate)
|
|||
|
|
{
|
|||
|
|
double hHp, hMp;
|
|||
|
|
LevelUpBurst.ComputeRecovery(hp, maxHp, mp, maxMp, hpRate, mpRate, out hHp, out hMp);
|
|||
|
|
L("| " + hp + "/" + maxHp + " | " + mp + "/" + maxMp + " | " + hpRate + "/" + mpRate +
|
|||
|
|
" | +" + hHp + " | +" + hMp + " | " + (hp + hHp) + " | " + (mp + hMp) + " |");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ── ⑤ GC ────────────────────────────────────────────────────────────────
|
|||
|
|
static void Section5_Gc()
|
|||
|
|
{
|
|||
|
|
L("## ⑤ GC (구독자 1 = LevelUpBurst · 스로틀 구간)");
|
|||
|
|
var data = MakeFakeData(30);
|
|||
|
|
|
|||
|
|
GrowthEvents.RaiseLevelUp(data, 31); // 예열 = 첫 스폰(할당 있음)을 측정 밖으로
|
|||
|
|
LevelUpBurst.DespawnLast();
|
|||
|
|
|
|||
|
|
long b0 = Warm();
|
|||
|
|
for (int i = 0; i < 1000; i++) GrowthEvents.RaiseLevelUp(null, 40 + i);
|
|||
|
|
long a0 = GC.GetTotalMemory(false);
|
|||
|
|
L("(a) RaiseLevelUp(data=null) × 1000 → GC 델타 = " + (a0 - b0) + " B (회당 " + ((a0 - b0) / 1000.0).ToString("F2") + " B)");
|
|||
|
|
|
|||
|
|
long b1 = Warm();
|
|||
|
|
for (int i = 0; i < 1000; i++) GrowthEvents.RaiseLevelUp(data, 40 + i);
|
|||
|
|
long a1 = GC.GetTotalMemory(false);
|
|||
|
|
L("(b) RaiseLevelUp(data=SD_PC) × 1000 → GC 델타 = " + (a1 - b1) + " B (회당 " + ((a1 - b1) / 1000.0).ToString("F2") + " B)");
|
|||
|
|
L(" ※ (b)−(a) 는 페이로드의 statPointTotal 이 부르는 **원본** SD_PC.Get_Point() → Get_UsePoint() 의 LINQ(Select/Sum) 할당이다.");
|
|||
|
|
|
|||
|
|
long b2 = Warm();
|
|||
|
|
for (int i = 0; i < 1000; i++) data.Get_Point();
|
|||
|
|
long a2 = GC.GetTotalMemory(false);
|
|||
|
|
L("(c) 원본 SD_PC.Get_Point() × 1000 (이벤트 없이) → GC 델타 = " + (a2 - b2) + " B (회당 " + ((a2 - b2) / 1000.0).ToString("F2") + " B)");
|
|||
|
|
L(" BurstSpawned=" + LevelUpBurst.BurstSpawned + " SkippedThrottle=" + LevelUpBurst.SkippedByThrottle + "(측정 구간은 전부 스로틀)");
|
|||
|
|
LevelUpBurst.DespawnLast();
|
|||
|
|
L("");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
static long Warm()
|
|||
|
|
{
|
|||
|
|
GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect();
|
|||
|
|
return GC.GetTotalMemory(true);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>GC 재측정 — 측정법의 민감도(대조군)까지 같이 낸다. 단독 실행 entry.</summary>
|
|||
|
|
public static object Gc2()
|
|||
|
|
{
|
|||
|
|
sb = new StringBuilder();
|
|||
|
|
L("# WL-813k GC 재측정 — " + DateTime.Now.ToString("HH:mm:ss"));
|
|||
|
|
LevelUpBurst.EnsureSubscribed();
|
|||
|
|
var data = MakeFakeData(30);
|
|||
|
|
GrowthEvents.RaiseLevelUp(data, 31); LevelUpBurst.DespawnLast(); // 예열(첫 스폰을 측정 밖으로)
|
|||
|
|
|
|||
|
|
Meas("대조군 new object() × 1000", () => { object o = null; for (int i = 0; i < 1000; i++) o = new object(); GC.KeepAlive(o); });
|
|||
|
|
Meas("대조군 원본 SD_PC.Get_Point() × 1000 (LINQ Select/Sum)", () => { int s = 0; for (int i = 0; i < 1000; i++) s += data.Get_Point(); GC.KeepAlive(s); });
|
|||
|
|
Meas("RaiseLevelUp(null) × 1000", () => { for (int i = 0; i < 1000; i++) GrowthEvents.RaiseLevelUp(null, 40 + i); });
|
|||
|
|
Meas("RaiseLevelUp(SD_PC) × 1000", () => { for (int i = 0; i < 1000; i++) GrowthEvents.RaiseLevelUp(data, 40 + i); });
|
|||
|
|
|
|||
|
|
L("BurstSpawned=" + LevelUpBurst.BurstSpawned + " SkippedThrottle=" + LevelUpBurst.SkippedByThrottle);
|
|||
|
|
LevelUpBurst.DespawnLast(); LevelUpBurst.Unsubscribe();
|
|||
|
|
L("Heavy count = " + EffectBudget.Count(EffectBudgetKind.Heavy) + " · 구독 해제 = " + (GrowthEvents.LevelUp.Count == 0));
|
|||
|
|
try { File.AppendAllText(OutPath, sb.ToString(), new UTF8Encoding(false)); } catch (Exception ex) { Debug.LogException(ex); }
|
|||
|
|
Debug.Log(sb.ToString());
|
|||
|
|
return sb.ToString();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
static void Meas(string name, Action act)
|
|||
|
|
{
|
|||
|
|
GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect();
|
|||
|
|
long g0 = GC.GetTotalMemory(true);
|
|||
|
|
long m0 = UnityEngine.Profiling.Profiler.GetMonoUsedSizeLong();
|
|||
|
|
act();
|
|||
|
|
long g1 = GC.GetTotalMemory(false);
|
|||
|
|
long m1 = UnityEngine.Profiling.Profiler.GetMonoUsedSizeLong();
|
|||
|
|
L(" " + name + " → GC.GetTotalMemory 델타 = " + (g1 - g0) + " B · Profiler.MonoUsed 델타 = " + (m1 - m0) + " B");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ── ⑥ C8 롤백 ───────────────────────────────────────────────────────────
|
|||
|
|
static void Section6_Rollback()
|
|||
|
|
{
|
|||
|
|
L("## ⑥ C8 롤백 (원본 100% 복귀)");
|
|||
|
|
var data = MakeFakeData(50);
|
|||
|
|
|
|||
|
|
GrowthEvents.ResetDiagnostics(); LevelUpBurst.ResetDiagnostics();
|
|||
|
|
|
|||
|
|
// (a) 성장 스위치 off
|
|||
|
|
WLGrowthSettings.RuntimeDisabled = true;
|
|||
|
|
GrowthEvents.RaiseLevelUp(data, 51);
|
|||
|
|
L("(a) WLGrowthSettings.RuntimeDisabled=true → Enabled=" + GrowthEvents.Enabled +
|
|||
|
|
" Raised=" + GrowthEvents.LevelUp.Raised + " TotalRaised=" + GrowthEvents.TotalRaised +
|
|||
|
|
" Handled=" + LevelUpBurst.Handled + " BurstSpawned=" + LevelUpBurst.BurstSpawned);
|
|||
|
|
WLGrowthSettings.RuntimeDisabled = false;
|
|||
|
|
|
|||
|
|
// (b) 코어 스위치 off
|
|||
|
|
WLCombatCoreSettings.RuntimeDisabled = true;
|
|||
|
|
GrowthEvents.RaiseLevelUp(data, 52);
|
|||
|
|
L("(b) WLCombatCoreSettings.RuntimeDisabled=true → Enabled=" + GrowthEvents.Enabled +
|
|||
|
|
" Raised=" + GrowthEvents.LevelUp.Raised + " TotalRaised=" + GrowthEvents.TotalRaised +
|
|||
|
|
" Handled=" + LevelUpBurst.Handled + " BurstSpawned=" + LevelUpBurst.BurstSpawned);
|
|||
|
|
WLCombatCoreSettings.RuntimeDisabled = false;
|
|||
|
|
|
|||
|
|
// (c) 설정 에셋 없음 (Resources 로드 결과를 null 로 강제 = 에셋 삭제와 같은 경로)
|
|||
|
|
var fCached = typeof(WLGrowthSettings).GetField("s_cached", BindingFlags.NonPublic | BindingFlags.Static);
|
|||
|
|
var fDone = typeof(WLGrowthSettings).GetField("s_lookupDone", BindingFlags.NonPublic | BindingFlags.Static);
|
|||
|
|
if (fCached != null && fDone != null)
|
|||
|
|
{
|
|||
|
|
fCached.SetValue(null, null); fDone.SetValue(null, true);
|
|||
|
|
GrowthEvents.RaiseLevelUp(data, 53);
|
|||
|
|
L("(c) 에셋 없음(Instance=null) → WLGrowthSettings.Enabled=" + WLGrowthSettings.Enabled +
|
|||
|
|
" GrowthEvents.Enabled=" + GrowthEvents.Enabled +
|
|||
|
|
" Raised=" + GrowthEvents.LevelUp.Raised + " TotalRaised=" + GrowthEvents.TotalRaised +
|
|||
|
|
" Handled=" + LevelUpBurst.Handled + " BurstSpawned=" + LevelUpBurst.BurstSpawned);
|
|||
|
|
WLGrowthSettings.ClearCache();
|
|||
|
|
L(" ClearCache 복구 → Instance=" + (WLGrowthSettings.Instance != null ? "found" : "NULL") + " Enabled=" + WLGrowthSettings.Enabled);
|
|||
|
|
}
|
|||
|
|
else L("(c) 리플렉션 실패 — 미검증");
|
|||
|
|
|
|||
|
|
// (d) 스위치 복구 후 정상 동작 확인
|
|||
|
|
LevelUpBurst.ResetDiagnostics(); GrowthEvents.ResetDiagnostics();
|
|||
|
|
GrowthEvents.RaiseLevelUp(data, 54);
|
|||
|
|
L("(d) 복구 후 → Raised=" + GrowthEvents.LevelUp.Raised + " Handled=" + LevelUpBurst.Handled +
|
|||
|
|
" BurstSpawned=" + LevelUpBurst.BurstSpawned + " instance=" + (LevelUpBurst.LastBurstInstance != null));
|
|||
|
|
LevelUpBurst.DespawnLast();
|
|||
|
|
L("");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ── ⑦ 정리 ──────────────────────────────────────────────────────────────
|
|||
|
|
static void Section7_Cleanup()
|
|||
|
|
{
|
|||
|
|
L("## ⑦ 정리");
|
|||
|
|
LevelUpBurst.DespawnLast();
|
|||
|
|
LevelUpBurst.Unsubscribe();
|
|||
|
|
WLGrowthSettings.RuntimeDisabled = false;
|
|||
|
|
WLCombatCoreSettings.RuntimeDisabled = false;
|
|||
|
|
L("구독 해제 = " + (GrowthEvents.LevelUp.Count == 0) + " · Heavy count = " + EffectBudget.Count(EffectBudgetKind.Heavy) +
|
|||
|
|
" · Acquired/Denied = " + EffectBudget.AcquiredCount + "/" + EffectBudget.DeniedCount);
|
|||
|
|
var sc = UnityEditor.SceneManagement.EditorSceneManager.GetActiveScene();
|
|||
|
|
L("활성 씬 = " + (string.IsNullOrEmpty(sc.name) ? "(none)" : sc.name) + " · dirty = " + sc.isDirty + " (저장하지 않는다)");
|
|||
|
|
var stray = UnityEngine.Object.FindObjectsByType<ParticleSystem>(FindObjectsSortMode.None);
|
|||
|
|
int fx = 0;
|
|||
|
|
for (int i = 0; i < stray.Length; i++) if (stray[i] != null && stray[i].transform.root.name.StartsWith("FX_FireLevelUp")) fx++;
|
|||
|
|
L("잔존 FX_FireLevelUp 파티클 = " + fx);
|
|||
|
|
L("");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ── 헬퍼 ────────────────────────────────────────────────────────────────
|
|||
|
|
static SD_PC MakeFakeData(int lv)
|
|||
|
|
{
|
|||
|
|
var d = new SD_PC();
|
|||
|
|
d.Lv = lv; d.Lv.RandomizeCryptoKey();
|
|||
|
|
return d;
|
|||
|
|
}
|
|||
|
|
}
|