213 lines
12 KiB
C#
213 lines
12 KiB
C#
|
|
// WL-816j — ⑥ 채택 상태 최종 확인: PD 경로(구조 재현) · 기능 무영향 · 성능 전/후 · 되돌리기 · 최종 캡처
|
|||
|
|
// 🔴 자기 완결 파일 · Play 중 에셋 수정 0(렌더러의 sharedMaterial 만 교체).
|
|||
|
|
using System.Collections;
|
|||
|
|
using System.Text;
|
|||
|
|
using UnityEngine;
|
|||
|
|
using UnityEngine.Rendering.Universal;
|
|||
|
|
using UnityEngine.SceneManagement;
|
|||
|
|
using FIIsland = CryingSnow.FarmingIsland.Island;
|
|||
|
|
|
|||
|
|
public static class WL816j_Final
|
|||
|
|
{
|
|||
|
|
public const string D = "Screenshots_WL/WL816j/";
|
|||
|
|
public static void Open()
|
|||
|
|
{
|
|||
|
|
UnityEditor.SceneManagement.EditorSceneManager.OpenScene(
|
|||
|
|
"Assets/Scenes/InGame.unity", UnityEditor.SceneManagement.OpenSceneMode.Single);
|
|||
|
|
Debug.Log("[816j] InGame 열림");
|
|||
|
|
}
|
|||
|
|
public static void Start()
|
|||
|
|
{
|
|||
|
|
var go = GameObject.Find("~WL816jFinal");
|
|||
|
|
if (go != null) Object.DestroyImmediate(go);
|
|||
|
|
go = new GameObject("~WL816jFinal");
|
|||
|
|
go.AddComponent<WL816j_FinalRunner>();
|
|||
|
|
Debug.Log("[816j] final 러너 시작");
|
|||
|
|
}
|
|||
|
|
public static Camera Look(string n, Vector3 pos, Vector3 at, float fov)
|
|||
|
|
{
|
|||
|
|
var go = GameObject.Find(n);
|
|||
|
|
if (go == null) { go = new GameObject(n); go.hideFlags = HideFlags.DontSave; }
|
|||
|
|
var c = go.GetComponent<Camera>(); if (c == null) c = go.AddComponent<Camera>();
|
|||
|
|
c.orthographic = false; c.fieldOfView = fov; c.nearClipPlane = 0.1f; c.farClipPlane = 2000f;
|
|||
|
|
c.clearFlags = CameraClearFlags.Skybox; c.cullingMask = ~0; c.depth = -100f;
|
|||
|
|
go.transform.position = pos; go.transform.LookAt(at);
|
|||
|
|
var a = go.GetComponent<UniversalAdditionalCameraData>();
|
|||
|
|
if (a == null) a = go.AddComponent<UniversalAdditionalCameraData>();
|
|||
|
|
a.renderPostProcessing = true;
|
|||
|
|
return c;
|
|||
|
|
}
|
|||
|
|
public static string Shot(Camera cam, string path, int w, int h)
|
|||
|
|
{
|
|||
|
|
if (cam == null) return "카메라 없음";
|
|||
|
|
System.IO.Directory.CreateDirectory(System.IO.Path.GetDirectoryName(path));
|
|||
|
|
var rt = new RenderTexture(w, h, 24, RenderTextureFormat.ARGB32, RenderTextureReadWrite.sRGB);
|
|||
|
|
rt.antiAliasing = 1; rt.Create();
|
|||
|
|
var pT = cam.targetTexture; var pA = RenderTexture.active;
|
|||
|
|
cam.targetTexture = rt; cam.Render(); RenderTexture.active = rt;
|
|||
|
|
var t = new Texture2D(w, h, TextureFormat.RGB24, false);
|
|||
|
|
t.ReadPixels(new Rect(0, 0, w, h), 0, 0); t.Apply();
|
|||
|
|
RenderTexture.active = pA; cam.targetTexture = pT; rt.Release(); Object.DestroyImmediate(rt);
|
|||
|
|
System.IO.File.WriteAllBytes(path, t.EncodeToPNG());
|
|||
|
|
var px = t.GetPixels32(); long r = 0, g = 0, b = 0; int n = 0;
|
|||
|
|
for (int i = 0; i < px.Length; i += 7) { r += px[i].r; g += px[i].g; b += px[i].b; n++; }
|
|||
|
|
Object.DestroyImmediate(t);
|
|||
|
|
return "평균 #" + ((int)(r / n)).ToString("X2") + ((int)(g / n)).ToString("X2") + ((int)(b / n)).ToString("X2") + " → " + path;
|
|||
|
|
}
|
|||
|
|
public static float Ms(Camera cam, int frames)
|
|||
|
|
{
|
|||
|
|
var rt = new RenderTexture(1080, 1920, 24, RenderTextureFormat.ARGB32, RenderTextureReadWrite.sRGB);
|
|||
|
|
rt.antiAliasing = 1; rt.Create();
|
|||
|
|
var pT = cam.targetTexture; cam.targetTexture = rt;
|
|||
|
|
for (int i = 0; i < 10; i++) cam.Render();
|
|||
|
|
var sw = System.Diagnostics.Stopwatch.StartNew();
|
|||
|
|
for (int i = 0; i < frames; i++) cam.Render();
|
|||
|
|
sw.Stop();
|
|||
|
|
cam.targetTexture = pT; rt.Release(); Object.DestroyImmediate(rt);
|
|||
|
|
return (float)sw.Elapsed.TotalMilliseconds / frames;
|
|||
|
|
}
|
|||
|
|
public static void Strip(string[] paths, string outPath)
|
|||
|
|
{
|
|||
|
|
var ts = new Texture2D[paths.Length]; int w = 0, h = 0;
|
|||
|
|
for (int i = 0; i < paths.Length; i++)
|
|||
|
|
{
|
|||
|
|
if (!System.IO.File.Exists(paths[i])) return;
|
|||
|
|
ts[i] = new Texture2D(2, 2, TextureFormat.RGB24, false);
|
|||
|
|
ts[i].LoadImage(System.IO.File.ReadAllBytes(paths[i]));
|
|||
|
|
w += ts[i].width; h = Mathf.Max(h, ts[i].height);
|
|||
|
|
}
|
|||
|
|
var o = new Texture2D(w, h, TextureFormat.RGB24, false);
|
|||
|
|
var f = new Color32[w * h];
|
|||
|
|
for (int i = 0; i < f.Length; i++) f[i] = new Color32(24, 24, 28, 255);
|
|||
|
|
o.SetPixels32(f);
|
|||
|
|
int x = 0;
|
|||
|
|
for (int i = 0; i < ts.Length; i++) { o.SetPixels32(x, 0, ts[i].width, ts[i].height, ts[i].GetPixels32()); x += ts[i].width; }
|
|||
|
|
o.Apply();
|
|||
|
|
System.IO.File.WriteAllBytes(outPath, o.EncodeToPNG());
|
|||
|
|
Object.DestroyImmediate(o);
|
|||
|
|
for (int i = 0; i < ts.Length; i++) Object.DestroyImmediate(ts[i]);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public class WL816j_FinalRunner : MonoBehaviour
|
|||
|
|
{
|
|||
|
|
static StringBuilder sb;
|
|||
|
|
static void L(string s) { sb.AppendLine(s); }
|
|||
|
|
const string D = WL816j_Final.D;
|
|||
|
|
const string MatDir = "Assets/WL/Look/Farm/Materials/";
|
|||
|
|
|
|||
|
|
void Start() { StartCoroutine(Co()); }
|
|||
|
|
|
|||
|
|
IEnumerator Co()
|
|||
|
|
{
|
|||
|
|
sb = new StringBuilder();
|
|||
|
|
L("=== WL-816j ⑥ 최종 확인 ===");
|
|||
|
|
bool viaGame = false;
|
|||
|
|
try { if (InGameInfo.Ins != null) { InGameInfo.Ins.Load_Map(900); viaGame = true; } }
|
|||
|
|
catch (System.Exception) { }
|
|||
|
|
L("Load_Map(900) = " + (viaGame ? "성공" : "🔴 로그인 없이는 못 탄다 → LoadSceneAsync(Level01, Additive)"));
|
|||
|
|
if (!viaGame)
|
|||
|
|
{
|
|||
|
|
var op = SceneManager.LoadSceneAsync("Level01", LoadSceneMode.Additive);
|
|||
|
|
while (op != null && !op.isDone) yield return null;
|
|||
|
|
}
|
|||
|
|
for (int i = 0; i < 7; i++) yield return new WaitForSeconds(1f);
|
|||
|
|
|
|||
|
|
Renderer water = null;
|
|||
|
|
foreach (var r in Object.FindObjectsByType<Renderer>(FindObjectsInactive.Exclude, FindObjectsSortMode.None))
|
|||
|
|
if (r != null && r.gameObject.scene.name == "Level01" && r.name == "Water") water = r;
|
|||
|
|
Camera live = null;
|
|||
|
|
foreach (var c in Object.FindObjectsByType<Camera>(FindObjectsInactive.Exclude, FindObjectsSortMode.None))
|
|||
|
|
{
|
|||
|
|
if (!c.gameObject.activeInHierarchy || !c.enabled || c.targetTexture != null) continue;
|
|||
|
|
if (c.name.StartsWith("~WL816j")) continue;
|
|||
|
|
if (live == null || c.depth > live.depth) live = c;
|
|||
|
|
}
|
|||
|
|
if (water == null || live == null) { L("🔴 물/카메라 없음"); Done(); yield break; }
|
|||
|
|
var adopted = water.sharedMaterial;
|
|||
|
|
L("");
|
|||
|
|
L("1) 물 = " + adopted.name + " · 셰이더 " + adopted.shader.name + " · 물 교체 " + WL.Look.Farm.WLIslandLook.WaterSwapped
|
|||
|
|
+ " · 렌더러 " + WL.Look.Farm.WLIslandLook.SwappedRenderers);
|
|||
|
|
var mc = water.GetComponent<MeshCollider>(); var mf = water.GetComponent<MeshFilter>();
|
|||
|
|
L(" 물 오브젝트 그대로인가 : MeshCollider=" + (mc ? "있음 enabled=" + mc.enabled + " mesh=" + (mc.sharedMesh ? mc.sharedMesh.name : "-") : "없음")
|
|||
|
|
+ " · MeshFilter=" + (mf && mf.sharedMesh ? mf.sharedMesh.name : "-")
|
|||
|
|
+ " · layer=" + water.gameObject.layer + " · pos=" + water.transform.position.ToString("F1")
|
|||
|
|
+ " · scale=" + water.transform.localScale.ToString("F0"));
|
|||
|
|
|
|||
|
|
// ── 2) 걷기 ────────────────────────────────────────────────
|
|||
|
|
var cc = Object.FindFirstObjectByType<CharacterController>(FindObjectsInactive.Exclude);
|
|||
|
|
if (cc != null)
|
|||
|
|
{
|
|||
|
|
var p0 = cc.transform.position; var dir = new Vector3(1f, 0f, 1f).normalized; float moved = 0f;
|
|||
|
|
for (int i = 0; i < 120 && moved < 6f; i++) { cc.Move(dir * 0.05f + Vector3.down * 0.05f); moved += 0.05f; yield return null; }
|
|||
|
|
var p1 = cc.transform.position;
|
|||
|
|
L("2) 걷기: " + p0.ToString("F2") + " → " + p1.ToString("F2") + " · 이동 "
|
|||
|
|
+ Vector3.Distance(new Vector3(p0.x, 0, p0.z), new Vector3(p1.x, 0, p1.z)).ToString("F2") + " m · grounded=" + cc.isGrounded);
|
|||
|
|
}
|
|||
|
|
else L("2) 걷기: CharacterController 없음");
|
|||
|
|
|
|||
|
|
// ── 3) 섬 확장 ─────────────────────────────────────────────
|
|||
|
|
var islands = Object.FindObjectsByType<FIIsland>(FindObjectsInactive.Exclude, FindObjectsSortMode.None);
|
|||
|
|
L("3) 섬 타일 " + islands.Length + " · 풀 " + WL.Look.Farm.WLIslandGrass.LastLog);
|
|||
|
|
FIIsland target = null;
|
|||
|
|
foreach (var isl in islands) if (isl != null && isl.IsUnlocked && isl.gameObject.activeInHierarchy) target = isl;
|
|||
|
|
if (target != null)
|
|||
|
|
{
|
|||
|
|
target.gameObject.SetActive(false); yield return new WaitForSeconds(2f);
|
|||
|
|
L(" 1칸 잠금 → " + WL.Look.Farm.WLIslandGrass.LastLog + " · 물 = " + water.sharedMaterial.name);
|
|||
|
|
target.gameObject.SetActive(true); yield return new WaitForSeconds(3f);
|
|||
|
|
L(" 다시 열기 → " + WL.Look.Farm.WLIslandGrass.LastLog + " · 물 = " + water.sharedMaterial.name
|
|||
|
|
+ " · 물 교체 누적 " + WL.Look.Farm.WLIslandLook.WaterSwapped + " (평면 1장이라 새 가장자리도 같은 물)");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ── 4) 성능 전(816h C)/후(816j D) 교대 2회 ──────────────────
|
|||
|
|
var C = UnityEditor.AssetDatabase.LoadAssetAtPath<Material>(MatDir + "Farm_Water_WL_C.mat");
|
|||
|
|
var FI = UnityEditor.AssetDatabase.LoadAssetAtPath<Material>(MatDir + "Farm_SimpleWater_Demo.mat");
|
|||
|
|
L("");
|
|||
|
|
L("4) 성능 (같은 카메라 1080×1920 · 60프레임 오프스크린 · 순서 교대 2회)");
|
|||
|
|
for (int round = 0; round < 2; round++)
|
|||
|
|
foreach (var pr in new[] { new object[] { "전(816h C)", C }, new object[] { "후(816j D)", adopted }, new object[] { "참고(FI SimpleWater)", FI } })
|
|||
|
|
{
|
|||
|
|
var m = pr[1] as Material; if (m == null) continue;
|
|||
|
|
water.sharedMaterial = m; yield return null; yield return null;
|
|||
|
|
L(" " + round + "회차 " + (string)pr[0] + " = " + WL816j_Final.Ms(live, 60).ToString("F3") + " ms/frame");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ── 5) 되돌리기 (화면으로) ──────────────────────────────────
|
|||
|
|
L("");
|
|||
|
|
L("5) 되돌리기 — waterTo 를 C 로 되돌리면 816h 그대로 · waterMode 0 이면 FI 물");
|
|||
|
|
water.sharedMaterial = C; yield return null; yield return new WaitForSeconds(0.3f);
|
|||
|
|
L(" waterTo=C " + WL816j_Final.Shot(live, D + "z_rollback_to_C.png", 1080, 1920));
|
|||
|
|
water.sharedMaterial = FI; yield return null; yield return new WaitForSeconds(0.3f);
|
|||
|
|
L(" waterMode=0 " + WL816j_Final.Shot(live, D + "z_rollback_to_FI.png", 1080, 1920));
|
|||
|
|
|
|||
|
|
// ── 6) 최종 캡처 ───────────────────────────────────────────
|
|||
|
|
water.sharedMaterial = C; yield return null; yield return new WaitForSeconds(0.3f);
|
|||
|
|
float zc = -3.78f, shoreX = 0f;
|
|||
|
|
for (float x = 4f; x < 90f; x += 0.25f)
|
|||
|
|
{ RaycastHit h; if (Physics.Raycast(new Vector3(x, 60f, zc), Vector3.down, out h, 200f) && h.point.y > -0.9f) shoreX = x; }
|
|||
|
|
var shore = WL816j_Final.Look("~WL816jFS", new Vector3(shoreX + 5.5f, 2.2f, zc + 5.5f), new Vector3(shoreX - 0.5f, -1f, zc - 0.5f), 32f);
|
|||
|
|
var horizon = WL816j_Final.Look("~WL816jFH", new Vector3(-14f, 8f, -14f), new Vector3(6f, 0f, 6f), 55f);
|
|||
|
|
L("");
|
|||
|
|
L("6) 최종 캡처");
|
|||
|
|
L(" [전 816h C] 게임 " + WL816j_Final.Shot(live, D + "n_before_game.png", 1080, 1920));
|
|||
|
|
L(" [전 816h C] 가장자리 " + WL816j_Final.Shot(shore, D + "n_before_shore.png", 720, 1280));
|
|||
|
|
L(" [전 816h C] 수평선 " + WL816j_Final.Shot(horizon, D + "n_before_horizon.png", 1080, 1920));
|
|||
|
|
water.sharedMaterial = adopted; yield return null; yield return new WaitForSeconds(0.3f);
|
|||
|
|
L(" [후 816j D] 게임 " + WL816j_Final.Shot(live, D + "n_after_game.png", 1080, 1920));
|
|||
|
|
L(" [후 816j D] 가장자리 " + WL816j_Final.Shot(shore, D + "n_after_shore.png", 720, 1280));
|
|||
|
|
L(" [후 816j D] 수평선 " + WL816j_Final.Shot(horizon, D + "n_after_horizon.png", 1080, 1920));
|
|||
|
|
WL816j_Final.Strip(new[] { D + "n_before_game.png", D + "n_after_game.png" }, D + "z_final_side_by_side.png");
|
|||
|
|
WL816j_Final.Strip(new[] { D + "n_before_shore.png", D + "n_after_shore.png" }, D + "z_final_shore_before_after.png");
|
|||
|
|
L(" 좌우 = z_final_side_by_side.png(좌 지금/우 채택) · z_final_shore_before_after.png(가장자리 확대 전/후)");
|
|||
|
|
|
|||
|
|
Done();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void Done()
|
|||
|
|
{
|
|||
|
|
System.IO.File.WriteAllText("AgentScripts/WL816j_FINAL.txt", sb.ToString());
|
|||
|
|
Debug.Log("[816j final]\n" + sb);
|
|||
|
|
}
|
|||
|
|
}
|