Project_WL/AgentScripts/WL816h_Probe.cs

210 lines
11 KiB
C#
Raw Normal View History

// WL-816h — ① 지금 상태 실측 (PD 실행 경로 · 하늘 · 물)
// PD 경로 재현 = InGame 을 활성 씬으로 Play → Level01 을 Additive (816f 와 같은 호출)
// 로그인은 워커 금지(§9)라 못 탄다 → 구조만 같게.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
using UnityEngine.SceneManagement;
public static class WL816h_Probe
{
public const string Dir = "Screenshots_WL/WL816h/";
public const int W = 1080, H = 1920;
public static void Open()
{
UnityEditor.SceneManagement.EditorSceneManager.OpenScene(
"Assets/Scenes/InGame.unity", UnityEditor.SceneManagement.OpenSceneMode.Single);
Debug.Log("[816h] InGame 열림");
}
public static void Start()
{
var go = GameObject.Find("~WL816hProbe");
if (go != null) Object.DestroyImmediate(go);
go = new GameObject("~WL816hProbe");
go.AddComponent<WL816h_ProbeRunner>();
Debug.Log("[816h] 러너 시작");
}
// ── 에디트 모드: 레퍼런스(아레나·데모) 씬의 하늘을 그대로 읽고 찍는다 ──
public static void RefScenes()
{
var sb = new System.Text.StringBuilder();
Ref(sb, "Assets/WL/Look/Arena/Scenes/WL_ArenaProto.unity", "arena");
Ref(sb, "Assets/LowPolyFantasyArena/Scenes/LowPolyArena_Demo.unity", "demo");
System.IO.File.WriteAllText("AgentScripts/WL816h_REF.txt", sb.ToString());
Debug.Log("[816h ref]\n" + sb);
}
static void Ref(System.Text.StringBuilder sb, string path, string tag)
{
UnityEditor.SceneManagement.EditorSceneManager.OpenScene(path, UnityEditor.SceneManagement.OpenSceneMode.Single);
sb.AppendLine("### " + tag + " " + path);
sb.AppendLine(WL816h_Util.SkyLine());
var cams = Object.FindObjectsByType<Camera>(FindObjectsInactive.Include, FindObjectsSortMode.None);
foreach (var c in cams)
{
var ac = c.GetComponent<UniversalAdditionalCameraData>();
sb.AppendLine(" CAM " + c.name + " active=" + c.gameObject.activeInHierarchy + " en=" + c.enabled
+ " ortho=" + c.orthographic + (c.orthographic ? (" size=" + c.orthographicSize) : (" fov=" + c.fieldOfView))
+ " clear=" + c.clearFlags + " post=" + (ac == null ? "noACD" : ac.renderPostProcessing.ToString()));
}
var vols = Object.FindObjectsByType<Volume>(FindObjectsInactive.Include, FindObjectsSortMode.None);
sb.AppendLine(" Volume 수 = " + vols.Length);
// 하늘만 보이는 카메라로 찍는다(수평선 위)
var cam = WL816h_Util.SkyCam();
sb.AppendLine(" 하늘 화면색 = " + WL816h_Util.Shot(cam, Dir + "ref_sky_" + tag + ".png", true));
Object.DestroyImmediate(cam.gameObject);
}
}
public static class WL816h_Util
{
public static string SkyLine()
{
return "RenderSettings: amb=" + RenderSettings.ambientMode + " light=" + F(RenderSettings.ambientLight)
+ " sky=" + F(RenderSettings.ambientSkyColor) + " I=" + RenderSettings.ambientIntensity
+ " skybox=" + (RenderSettings.skybox ? RenderSettings.skybox.name + "/" + RenderSettings.skybox.shader.name : "없음")
+ " fog=" + RenderSettings.fog + " refl=" + RenderSettings.defaultReflectionMode
+ "/" + RenderSettings.reflectionIntensity
+ " sun=" + (RenderSettings.sun ? RenderSettings.sun.name : "없음");
}
public static string F(Color c) { return "(" + c.r.ToString("F3") + "," + c.g.ToString("F3") + "," + c.b.ToString("F3") + ")"; }
/// <summary>수평선 위만 잡는 카메라 — 화면의 대부분이 하늘이다.</summary>
public static Camera SkyCam()
{
var go = new GameObject("~WL816hSkyCam"); go.hideFlags = HideFlags.DontSave;
var c = go.AddComponent<Camera>();
c.orthographic = false; c.fieldOfView = 50f;
c.nearClipPlane = 0.3f; c.farClipPlane = 2000f;
c.clearFlags = CameraClearFlags.Skybox; c.cullingMask = ~0; c.depth = -100f;
go.transform.position = new Vector3(0f, 40f, 0f);
go.transform.rotation = Quaternion.Euler(-16f, 30f, 0f); // 위를 본다 = 하늘만
if (go.GetComponent<UniversalAdditionalCameraData>() == null) go.AddComponent<UniversalAdditionalCameraData>();
return c;
}
/// <summary>오프스크린 렌더 → PNG. 반환 = 화면 평균색(#RRGGBB).</summary>
public static string Shot(Camera cam, string path, bool wantAvg)
{
if (cam == null) return "카메라 없음";
System.IO.Directory.CreateDirectory(System.IO.Path.GetDirectoryName(path));
var rt = new RenderTexture(WL816h_Probe.W, WL816h_Probe.H, 24, RenderTextureFormat.ARGB32, RenderTextureReadWrite.sRGB);
rt.antiAliasing = 1; rt.Create();
var prevT = cam.targetTexture; var prevA = RenderTexture.active;
cam.targetTexture = rt; cam.Render();
RenderTexture.active = rt;
var tex = new Texture2D(WL816h_Probe.W, WL816h_Probe.H, TextureFormat.RGB24, false);
tex.ReadPixels(new Rect(0, 0, WL816h_Probe.W, WL816h_Probe.H), 0, 0); tex.Apply();
RenderTexture.active = prevA; cam.targetTexture = prevT;
System.IO.File.WriteAllBytes(path, tex.EncodeToPNG());
string avg = "";
if (wantAvg)
{
var px = tex.GetPixels32();
long r = 0, g = 0, b = 0;
for (int i = 0; i < px.Length; i++) { r += px[i].r; g += px[i].g; b += px[i].b; }
avg = "#" + ((int)(r / px.Length)).ToString("X2") + ((int)(g / px.Length)).ToString("X2") + ((int)(b / px.Length)).ToString("X2");
}
Object.DestroyImmediate(tex); rt.Release(); Object.DestroyImmediate(rt);
return avg + " → " + path;
}
}
public class WL816h_ProbeRunner : MonoBehaviour
{
static System.Text.StringBuilder sb;
void Start() { StartCoroutine(Co()); }
static void L(string s) { sb.AppendLine(s); }
IEnumerator Co()
{
sb = new System.Text.StringBuilder();
L("=== WL-816h 지금 상태 (PD 경로 = InGame 활성 + Level01 Additive) ===");
L("t0 활성씬=" + SceneManager.GetActiveScene().name + " / " + WL816h_Util.SkyLine());
bool viaGame = false;
try { if (InGameInfo.Ins != null) { InGameInfo.Ins.Load_Map(900); viaGame = true; } }
catch (System.Exception e) { L("Load_Map 예외(=로그인 없이는 못 탄다): " + e.GetType().Name); }
if (!viaGame)
{
L("→ SceneInfo.Load_AddScene 과 같은 호출로 대체: LoadSceneAsync(\"Level01\", Additive)");
var op = SceneManager.LoadSceneAsync("Level01", LoadSceneMode.Additive);
while (op != null && !op.isDone) yield return null;
}
for (int i = 0; i < 6; i++) yield return new WaitForSeconds(1f);
L("");
L("t+6s 활성씬=" + SceneManager.GetActiveScene().name + " sceneCount=" + SceneManager.sceneCount);
L("🔴 " + WL816h_Util.SkyLine());
L("IslandLook: 렌더러 " + WL.Look.Farm.WLIslandLook.SwappedRenderers + " light=" + WL.Look.Farm.WLIslandLook.LightingApplied
+ " refLook=" + WL.Look.Farm.WLIslandLook.ReferenceLookApplied);
L("RefLook : applied=" + WL.Look.Arena.WLReferenceLook.IsApplied + " log=" + WL.Look.Arena.WLReferenceLook.LastLog);
// ── 🔴 카메라 · 포스트 — 아레나 무드가 「보이는 카메라」에 실제로 걸렸나 ──
L("");
Camera live = null;
var cams = Object.FindObjectsByType<Camera>(FindObjectsInactive.Include, FindObjectsSortMode.None);
foreach (var c in cams)
{
bool isLive = c.gameObject.activeInHierarchy && c.enabled && c.targetTexture == null;
var ac = c.GetComponent<UniversalAdditionalCameraData>();
L("CAM " + c.name + " scene=" + c.gameObject.scene.name + " live=" + isLive + " depth=" + c.depth
+ " tag=" + c.tag + " clear=" + c.clearFlags
+ " 🔴post=" + (ac == null ? "noACD" : ac.renderPostProcessing.ToString()));
if (isLive && (live == null || c.depth > live.depth)) live = c;
}
L("→ 보이는 카메라 = " + (live == null ? "없음" : live.name + "(" + live.gameObject.scene.name + ")"));
L("Camera.main = " + (Camera.main == null ? "없음" : Camera.main.name + "(" + Camera.main.gameObject.scene.name + ")"));
var vols = Object.FindObjectsByType<Volume>(FindObjectsInactive.Include, FindObjectsSortMode.None);
foreach (var v in vols) L("Volume " + v.name + " global=" + v.isGlobal + " w=" + v.weight + " prio=" + v.priority
+ " profile=" + (v.sharedProfile ? v.sharedProfile.name : "없음"));
// ── 물 ──
L("");
foreach (var r in Object.FindObjectsByType<Renderer>(FindObjectsInactive.Include, FindObjectsSortMode.None))
{
if (r == null || r.gameObject.scene.name != "Level01") continue;
var m = r.sharedMaterial;
if (m == null || m.shader == null) continue;
if (!m.shader.name.ToLower().Contains("water") && !r.name.ToLower().Contains("water")) continue;
L("WATER obj=" + r.name + " layer=" + r.gameObject.layer + " mat=" + m.name + " shader=" + m.shader.name
+ " queue=" + m.renderQueue + " bounds=" + r.bounds.size.ToString("F0") + " pos=" + r.transform.position.ToString("F1"));
}
// ── URP 렌더러가 Opaque/Depth 텍스처를 주나(ToonWaterU 가 요구) ──
var urp = GraphicsSettings.defaultRenderPipeline as UniversalRenderPipelineAsset;
L("URP asset = " + (urp == null ? "없음" : urp.name + " opaqueTex=" + urp.supportsCameraOpaqueTexture
+ " depthTex=" + urp.supportsCameraDepthTexture + " msaa=" + urp.msaaSampleCount));
// ── 캡처 ──
L("");
L("하늘(섬) = " + WL816h_Util.Shot(WL816h_Util.SkyCam(), WL816h_Probe.Dir + "a_now_sky.png", true));
L("섬 화면 = " + WL816h_Util.Shot(live, WL816h_Probe.Dir + "a_now_island.png", true));
L("물 근접 = " + WL816h_Util.Shot(WaterCam(), WL816h_Probe.Dir + "a_now_water.png", true));
System.IO.File.WriteAllText("AgentScripts/WL816h_PROBE.txt", sb.ToString());
Debug.Log("[816h probe 완료]\n" + sb);
}
/// <summary>물이 화면의 절반을 차지하는 카메라(섬 가장자리 바깥).</summary>
public static Camera WaterCam()
{
var go = GameObject.Find("~WL816hWaterCam");
if (go == null) { go = new GameObject("~WL816hWaterCam"); go.hideFlags = HideFlags.DontSave; }
var c = go.GetComponent<Camera>(); if (c == null) c = go.AddComponent<Camera>();
c.orthographic = false; c.fieldOfView = 45f;
c.nearClipPlane = 0.3f; c.farClipPlane = 2000f;
c.clearFlags = CameraClearFlags.Skybox; c.cullingMask = ~0; c.depth = -100f;
go.transform.position = new Vector3(-18f, 6f, -18f);
go.transform.rotation = Quaternion.Euler(12f, 45f, 0f);
if (go.GetComponent<UniversalAdditionalCameraData>() == null) go.AddComponent<UniversalAdditionalCameraData>();
return c;
}
}