using System.Collections; using System.Collections.Generic; using System.IO; using UnityEngine; namespace TKS.OutGame { /// /// 타이틀 화면 검증 캡처(PD 2026-11-13 · 에디터 TKS.EditorTools.TitleCapture.Capture 가 SessionState 로 출력 폴더를 넘기면 생성 · 메모리 세이브). /// 등장 연출(연출 시계를 정해 찍음) · 끝 모습 1080×1920 · 화면비 1080×2400 · 1536×2048 · 대기 움직임 연속(실시간) · 누름 → 로비 확인 · 끝나면 스스로 종료. /// UICaptureDriver(다른 세션 작업 중)와 따로 둔다. /// public class TitleCaptureDriver : MonoBehaviour { public const string DirKey = "TKS_TITLE_CAPTURE_DIR"; public string OutputDir; readonly List log = new List(); #if UNITY_EDITOR [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)] static void AutoSpawn() { string dir = UnityEditor.SessionState.GetString(DirKey, ""); if (string.IsNullOrEmpty(dir)) return; UnityEditor.SessionState.EraseString(DirKey); new GameObject("TitleCaptureDriver").AddComponent().OutputDir = dir; } #endif IEnumerator Start() { Directory.CreateDirectory(OutputDir); yield return null; yield return null; var cam = Camera.main; if (cam == null) { Log("FAIL: 카메라 없음"); Finish(1); yield break; } bool started = false; TitleScreen.ForceShow = true; var ts = TitleScreen.Show(cam, () => started = true); Log("heroes=" + ts.Heroes.Count + " introEnd=" + ts.IntroEnd.ToString("0.00") + " provider=" + (BootFlow.TitleProvider != null)); // 등장 연출 — 연출 시계를 정해 한 장씩(캡처 시간에 흔들리지 않게) float[] at = { 0.15f, 0.35f, 0.55f, 0.75f, 0.95f, 1.15f, 1.35f, 1.42f, 1.50f, 1.60f, 1.75f }; // 로고 내려앉는 중간(1.30~1.72) 3장 = QA r1 U2 int i = 1; foreach (var t in at) { ts.SetTime(t); yield return null; yield return CaptureUtil.Capture(cam, 1080, 1920, Path.Combine(OutputDir, "intro_" + (i++).ToString("00") + "_" + t.ToString("0.00") + ".png")); } ts.SetTime(ts.IntroEnd + 1.2f); yield return null; yield return UiLayerProbe.Measure("title", Log, OutputDir); yield return CaptureUtil.Capture(cam, 1080, 1920, Path.Combine(OutputDir, "title_1080x1920.png")); yield return CaptureUtil.Capture(cam, 1080, 2400, Path.Combine(OutputDir, "title_1080x2400.png")); yield return CaptureUtil.Capture(cam, 1536, 2048, Path.Combine(OutputDir, "title_1536x2048.png")); // 대기 움직임(실시간 · 약 0.12 초 간격) — 실제 간격을 로그에 남김 float t0 = Time.unscaledTime; for (int k = 0; k < 24; k++) { yield return CaptureUtil.Capture(cam, 540, 960, Path.Combine(OutputDir, "idle_" + k.ToString("00") + ".png")); Log("idle " + k + " t=" + (Time.unscaledTime - t0).ToString("0.000")); float w = Time.unscaledTime + 0.12f; while (Time.unscaledTime < w) yield return null; } // 확인 영상용 실시간 연속(처음부터 다시 띄워 등장 → 대기 약 4 초 · 원본 크기 · 찍힌 실제 시각을 로그에 = 영상 프레임 길이) ts.Close(); yield return null; ts = TitleScreen.Show(cam, () => started = true); string vdir = Path.Combine(OutputDir, "video"); Directory.CreateDirectory(vdir); float v0 = Time.unscaledTime; var vlog = new List(); for (int k = 0; Time.unscaledTime - v0 < ts.IntroEnd + 4f && k < 400; k++) { float vt = Time.unscaledTime - v0; yield return CaptureUtil.Capture(cam, 1080, 1920, Path.Combine(vdir, "v" + k.ToString("000") + ".png")); vlog.Add(k + "," + vt.ToString("0.000", System.Globalization.CultureInfo.InvariantCulture)); } File.WriteAllLines(Path.Combine(vdir, "times.csv"), vlog.ToArray()); Log("video frames=" + vlog.Count + " seconds=" + (Time.unscaledTime - v0).ToString("0.00")); ts.SkipIntro(); float ready = Time.unscaledTime + 2f; while (!ts.PressReady && Time.unscaledTime < ready) yield return null; // 누름 → 페이드 → 로비 ts.Press(); float until = Time.unscaledTime + 4f; while (!started && Time.unscaledTime < until) yield return null; Log("pressed → started=" + started + " titleGone=" + (TitleScreen.Current == null)); yield return new WaitForSecondsRealtime(0.6f); yield return CaptureUtil.Capture(cam, 1080, 1920, Path.Combine(OutputDir, "after_press.png")); TitleScreen.ForceShow = false; Finish(started ? 0 : 1); } void Log(string s) { log.Add(s); Debug.Log("[TitleCapture] " + s); try { File.WriteAllLines(Path.Combine(OutputDir, "capture_log.txt"), log.ToArray()); } catch { } } void Finish(int code) { Log("finish code=" + code); #if UNITY_EDITOR UnityEditor.EditorApplication.Exit(code); #else Application.Quit(code); #endif } } }