diff --git a/AgentScripts/WL814b_Import.cs b/AgentScripts/WL814b_Import.cs
new file mode 100644
index 000000000..58e236824
--- /dev/null
+++ b/AgentScripts/WL814b_Import.cs
@@ -0,0 +1,78 @@
+// WL-814b — Assets/3DPixelCamera/URP.unitypackage 해제(BuiltIn 은 절대 건드리지 않는다).
+// 게임 코드 아님. run_script 전용.
+public static class WL814b_Import
+{
+ const string Pkg = "Assets/3DPixelCamera/URP.unitypackage";
+ const string Dir = "Assets/3DPixelCamera/URP";
+
+ /// 1단계 — 스냅샷을 찍고 비동기 임포트를 시작한다.
+ public static string Run()
+ {
+ if (!System.IO.File.Exists(Pkg)) return "FAIL 패키지 없음: " + Pkg;
+
+ var sb = new System.Text.StringBuilder();
+ sb.AppendLine("[WL814b-import] before: URP 폴더 존재=" + System.IO.Directory.Exists(Dir));
+ UnityEditor.AssetDatabase.ImportPackage(Pkg, false); // false = 대화상자 없이 전부
+ sb.AppendLine("[WL814b-import] ImportPackage 호출됨(비동기) — 다음 단계에서 Verify");
+ return sb.ToString();
+ }
+
+ /// 2단계 — 생긴 파일 목록·GUID 를 뱉는다.
+ public static string Verify()
+ {
+ UnityEditor.AssetDatabase.Refresh();
+ var sb = new System.Text.StringBuilder();
+ if (!System.IO.Directory.Exists(Dir)) { sb.AppendLine("FAIL URP 폴더 없음"); return sb.ToString(); }
+
+ var files = System.IO.Directory.GetFiles(Dir, "*", System.IO.SearchOption.AllDirectories);
+ System.Array.Sort(files);
+ int n = 0;
+ foreach (var f in files)
+ {
+ var rel = f.Replace('\\', '/');
+ int i = rel.IndexOf("Assets/");
+ if (i >= 0) rel = rel.Substring(i);
+ if (rel.EndsWith(".meta")) { sb.AppendLine(" meta " + rel); continue; }
+ n++;
+ var guid = UnityEditor.AssetDatabase.AssetPathToGUID(rel);
+ var t = UnityEditor.AssetDatabase.GetMainAssetTypeAtPath(rel);
+ sb.AppendLine(" ASSET " + rel + " | guid=" + guid + " | type=" + (t == null ? "?" : t.Name)
+ + " | " + new System.IO.FileInfo(f).Length + " B");
+ }
+ sb.AppendLine("[WL814b-import] 에셋 " + n + "개(+meta) · BuiltIn 해제 0");
+
+ // 프리팹 구조 표
+ var pf = UnityEditor.AssetDatabase.LoadAssetAtPath(Dir + "/PixelCameraSystem.prefab");
+ if (pf == null) sb.AppendLine("FAIL PixelCameraSystem.prefab 로드 실패");
+ else { sb.AppendLine("[구조]"); Dump(pf.transform, 0, sb); }
+ return sb.ToString();
+ }
+
+ static void Dump(UnityEngine.Transform t, int depth, System.Text.StringBuilder sb)
+ {
+ sb.Append(' ', depth * 2).Append("- ").Append(t.name).Append(" layer=").Append(t.gameObject.layer);
+ var comps = t.GetComponents();
+ sb.Append(" [");
+ for (int i = 0; i < comps.Length; i++)
+ {
+ if (comps[i] == null) { sb.Append(" "); continue; }
+ sb.Append(comps[i].GetType().Name).Append(' ');
+ }
+ sb.Append("]");
+ var cam = t.GetComponent();
+ if (cam != null)
+ sb.Append(" cam(ortho=").Append(cam.orthographic ? 1 : 0).Append(" size=").Append(cam.orthographicSize)
+ .Append(" depth=").Append(cam.depth).Append(" mask=").Append(cam.cullingMask)
+ .Append(" clear=").Append((int)cam.clearFlags).Append(" near=").Append(cam.nearClipPlane)
+ .Append(" far=").Append(cam.farClipPlane).Append(")");
+ var ucd = t.GetComponent();
+ if (ucd != null) sb.Append(" urp(type=").Append(ucd.renderType).Append(" post=").Append(ucd.renderPostProcessing ? 1 : 0).Append(")");
+ var mr = t.GetComponent();
+ if (mr != null) sb.Append(" mat=").Append(mr.sharedMaterial == null ? "null" : mr.sharedMaterial.name);
+ var lp = t.localPosition; var ls = t.localScale;
+ sb.Append(" lp=(").Append(lp.x.ToString("0.####")).Append(',').Append(lp.y.ToString("0.####")).Append(',').Append(lp.z.ToString("0.####")).Append(')');
+ sb.Append(" ls=(").Append(ls.x.ToString("0.####")).Append(',').Append(ls.y.ToString("0.####")).Append(',').Append(ls.z.ToString("0.####")).Append(')');
+ sb.AppendLine();
+ for (int i = 0; i < t.childCount; i++) Dump(t.GetChild(i), depth + 1, sb);
+ }
+}
diff --git a/AgentScripts/WL814b_Probe.cs b/AgentScripts/WL814b_Probe.cs
new file mode 100644
index 000000000..92adece0e
--- /dev/null
+++ b/AgentScripts/WL814b_Probe.cs
@@ -0,0 +1,637 @@
+// PD 지시 #814 · 발주서 WL-814b — Critter 픽셀 카메라 리그 검증 프로브 + 룩 캡처
+// (에디트 모드 전용 · Play 0 · 로그인 0 · 디스크 에셋 무수정)
+//
+// 실행 (CLAUDE.md §1: using 금지 · 네임스페이스 풀어 쓰기)
+// unity command run_script --file AgentScripts/WL814b_Probe.cs --entry WL814b_Probe.MakeAsset --timeout 300
+// unity command run_script --file AgentScripts/WL814b_Probe.cs --entry WL814b_Probe.Edit --timeout 1800
+//
+// 무엇을 재는가
+// A. 표 ① 보조 — 원본 Main Camera.prefab 값 · NewGameUI 캔버스 렌더 모드/카메라 · UICamera 스택
+// B. 리그 — 임시 씬(추가 로드 · 저장 0)에 맵 + PC + 잡몹 + 원본 카메라 → 조립 → 구조 표
+// C. 복원 — 원본 카메라 값 스냅샷 == 복원값(문자열 동일) · 리그 오브젝트 0 · RT 해제
+// D. 매핑오차 — Camera.main 투영(WorldToViewportPoint) vs 실제 RT→쿼드→뷰 카메라 화면 좌표(5점 · px)
+// E. GC — 프록시 미러 · 회전 스냅 판정 200k 회 할당 증가분(0 B 목표)
+// F. C8 — RuntimeDisabled = true → Tick 이 즉시 복원 · 조립 0
+// G. 캡처 — 1080×1920 4장(ortho 3.8×480 · 3.8×360 · 4.6×480 · 대조 원근 원본)
+public static class WL814b_Probe
+{
+ const string kOutDir = @"E:\NerdNavis\nn_himminji\Screenshots_WL\WL814b";
+ const string kMap = "Assets/Res_Addr/Map/WL_Nature.prefab";
+ const string kPc = "Assets/Res_Addr/PC/Ai01.prefab";
+ const string kCam = "Assets/ResWork/Prefabs/Ingame/Main Camera.prefab";
+ const string kRig = "Assets/3DPixelCamera/URP/PixelCameraSystem.prefab";
+ const string kSo = "Assets/WL/Combat/Settings/Resources/WL/WLPixelCameraSettings.asset";
+ const string kSnap = "AgentScripts/staging/WL814b/EDIT_PROBE.txt";
+
+ const int W = 1080, H = 1920;
+
+ static System.Text.StringBuilder sb;
+ static int pass, fail;
+ static UnityEngine.Vector3 s_lookAtWorld;
+
+ static void L(string s) { sb.Append(s).Append('\n'); }
+ static void Chk(bool ok, string label, string detail)
+ {
+ if (ok) pass++; else fail++;
+ sb.Append(ok ? " PASS " : " FAIL ").Append(label);
+ if (!string.IsNullOrEmpty(detail)) sb.Append(" ").Append(detail);
+ sb.Append('\n');
+ }
+
+ // ─────────────────────────────────────────────────────────────────────────
+ // SO 에셋 생성 (1회) — 손으로 YAML 쓰지 않고 에디터가 만들게 한다
+ // ─────────────────────────────────────────────────────────────────────────
+ public static string MakeAsset()
+ {
+ sb = new System.Text.StringBuilder();
+ var dir = System.IO.Path.GetDirectoryName(kSo).Replace('\\', '/');
+ if (!System.IO.Directory.Exists(dir)) { L("FAIL 폴더 없음 " + dir); return sb.ToString(); }
+
+ var so = UnityEditor.AssetDatabase.LoadAssetAtPath(kSo);
+ bool created = false;
+ if (so == null)
+ {
+ so = UnityEngine.ScriptableObject.CreateInstance();
+ UnityEditor.AssetDatabase.CreateAsset(so, kSo);
+ created = true;
+ }
+
+ var rig = UnityEditor.AssetDatabase.LoadAssetAtPath(kRig);
+ so.pixelCameraSystemPrefab = rig;
+ UnityEditor.EditorUtility.SetDirty(so);
+ UnityEditor.AssetDatabase.SaveAssets();
+ UnityEditor.AssetDatabase.Refresh();
+
+ L((created ? "생성" : "갱신") + " " + kSo);
+ L(" prefab=" + (rig == null ? "null(패키지 해제 확인)" : UnityEditor.AssetDatabase.GetAssetPath(rig)));
+ L(" guid=" + UnityEditor.AssetDatabase.AssetPathToGUID(kSo));
+ L(" enabled=" + so.enabled + " orthoSize=" + so.orthoSize + " pixelHeight=" + so.pixelHeight
+ + " rigLayer=" + so.rigLayer + " proxyMode=" + so.proxyMode
+ + " compensateViewZoom=" + so.compensateViewZoom);
+ return sb.ToString();
+ }
+
+ // ─────────────────────────────────────────────────────────────────────────
+ // 본 프로브
+ // ─────────────────────────────────────────────────────────────────────────
+ public static string Edit()
+ {
+ sb = new System.Text.StringBuilder();
+ pass = fail = 0;
+ System.IO.Directory.CreateDirectory(kOutDir);
+
+ L("# WL-814b 프로브 — " + System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
+ L("unity=" + UnityEngine.Application.unityVersion + " · isPlaying=" + UnityEngine.Application.isPlaying);
+
+ SectionA();
+
+ // 배치모드 에디터의 현재(무제목·빈) 씬에 직접 짓는다 — 추가 씬 생성은 무제목 씬이 열려 있으면 금지된다.
+ // 모든 인스턴스는 HideAndDontSave + DestroyImmediate 이므로 씬에 남지도, 저장되지도 않는다(811o 방식).
+ var scene = UnityEngine.SceneManagement.SceneManager.GetActiveScene();
+ L("현재 씬 = '" + scene.name + "' path='" + scene.path + "' dirty(before)=" + scene.isDirty
+ + " rootCount=" + scene.rootCount);
+
+ UnityEngine.GameObject mapGo = null, pcGo = null, camGo = null, lightGo = null;
+ var mobs = new System.Collections.Generic.List();
+ try
+ {
+ BuildScene(ref mapGo, ref pcGo, ref camGo, ref lightGo, mobs);
+ if (camGo == null) { L("FAIL 카메라 인스턴스 실패 — 중단"); }
+ else
+ {
+ var cam = camGo.GetComponent();
+ SectionBCD(cam, pcGo);
+ SectionE(cam);
+ SectionF(cam);
+ SectionG(cam);
+ }
+ }
+ catch (System.Exception ex) { L("EXCEPTION " + ex.GetType().Name + " " + ex.Message); L(ex.StackTrace); fail++; }
+ finally
+ {
+ WL.PixelArt.PixelCameraRig.Teardown("probe end");
+ WL.PixelArt.WLPixelCameraSettings.RuntimeDisabled = false;
+ for (int i = 0; i < mobs.Count; i++) if (mobs[i] != null) UnityEngine.Object.DestroyImmediate(mobs[i]);
+ if (pcGo != null) UnityEngine.Object.DestroyImmediate(pcGo);
+ if (camGo != null) UnityEngine.Object.DestroyImmediate(camGo);
+ if (mapGo != null) UnityEngine.Object.DestroyImmediate(mapGo);
+ if (lightGo != null) UnityEngine.Object.DestroyImmediate(lightGo);
+ var after = UnityEngine.SceneManagement.SceneManager.GetActiveScene();
+ L("씬 정리 후: dirty=" + after.isDirty + " rootCount=" + after.rootCount + " (저장 0)");
+ }
+
+ L("");
+ L("RESULT " + (fail == 0 ? "PASS" : "FAIL") + " " + pass + "/" + (pass + fail));
+ var outPath = kSnap;
+ System.IO.Directory.CreateDirectory(System.IO.Path.GetDirectoryName(outPath));
+ System.IO.File.WriteAllText(outPath, sb.ToString(), new System.Text.UTF8Encoding(false));
+ return sb.ToString();
+ }
+
+ // ── A. 표 ① 보조 실측 ────────────────────────────────────────────────────
+ static void SectionA()
+ {
+ L("");
+ L("## A. 원본 카메라 · UI 캔버스 실측");
+ var camPf = UnityEditor.AssetDatabase.LoadAssetAtPath(kCam);
+ if (camPf == null) { L("FAIL Main Camera.prefab 로드 실패"); fail++; return; }
+ var c = camPf.GetComponent();
+ var rc = camPf.GetComponent("RealCamera");
+ var al = camPf.GetComponent();
+ var mrv = camPf.GetComponent("MeshRendererVisibility");
+ var ucd = camPf.GetComponent();
+ L("Main Camera.prefab: tag=" + camPf.tag + " layer=" + camPf.layer + " parent=" + (camPf.transform.parent == null ? "none" : camPf.transform.parent.name)
+ + " children=" + camPf.transform.childCount);
+ L(" Camera: ortho=" + c.orthographic + " fov=" + c.fieldOfView + " size=" + c.orthographicSize
+ + " near=" + c.nearClipPlane + " far=" + c.farClipPlane + " depth=" + c.depth
+ + " mask=" + c.cullingMask + " clear=" + c.clearFlags + " hdr=" + c.allowHDR + " msaa=" + c.allowMSAA
+ + " occlusionCulling=" + c.useOcclusionCulling);
+ if (ucd != null)
+ L(" URP: type=" + ucd.renderType + " post=" + ucd.renderPostProcessing + " shadows=" + ucd.renderShadows
+ + " volumeMask=" + ucd.volumeLayerMask.value + " aa=" + ucd.antialiasing
+ + " stack=" + (ucd.cameraStack == null ? -1 : ucd.cameraStack.Count));
+ L(" 컴포넌트: RealCamera=" + (rc != null) + " AudioListener=" + (al != null) + " MeshRendererVisibility=" + (mrv != null));
+ Chk(rc != null && al != null, "원본 카메라 = RealCamera + AudioListener 보유(재부모화·비활성 금지 근거)", "");
+
+ var uiPf = UnityEditor.AssetDatabase.LoadAssetAtPath("Assets/Res_Addr/MainUI/NewGameUI.prefab");
+ if (uiPf != null)
+ {
+ var canvases = uiPf.GetComponentsInChildren(true);
+ L("NewGameUI.prefab 캔버스 " + canvases.Length + "개");
+ for (int i = 0; i < canvases.Length; i++)
+ {
+ var cv = canvases[i];
+ L(" [" + i + "] " + cv.name + " renderMode=" + cv.renderMode
+ + " worldCamera=" + (cv.worldCamera == null ? "null" : cv.worldCamera.name)
+ + " planeDistance=" + cv.planeDistance + " sortingOrder=" + cv.sortingOrder + " layer=" + cv.gameObject.layer);
+ }
+ var cams = uiPf.GetComponentsInChildren(true);
+ for (int i = 0; i < cams.Length; i++)
+ L(" UI camera: " + cams[i].name + " ortho=" + cams[i].orthographic + " depth=" + cams[i].depth
+ + " mask=" + cams[i].cullingMask + " clear=" + cams[i].clearFlags);
+ bool ssc = false;
+ for (int i = 0; i < canvases.Length; i++) if (canvases[i].renderMode == UnityEngine.RenderMode.ScreenSpaceCamera) ssc = true;
+ Chk(ssc, "인게임 UI 캔버스 = Screen Space - Camera(UICamera) → 원본 카메라를 끄면 UI 가 사라진다", "");
+ }
+ else { L("FAIL NewGameUI.prefab 로드 실패"); fail++; }
+ }
+
+ // ── 씬 조립 ──────────────────────────────────────────────────────────────
+ static void BuildScene(ref UnityEngine.GameObject mapGo, ref UnityEngine.GameObject pcGo,
+ ref UnityEngine.GameObject camGo, ref UnityEngine.GameObject lightGo,
+ System.Collections.Generic.List mobs)
+ {
+ L("");
+ L("## B. 임시 씬(추가 로드 · 저장 0)");
+
+ var mapPf = UnityEditor.AssetDatabase.LoadAssetAtPath(kMap);
+ if (mapPf != null) { mapGo = UnityEngine.Object.Instantiate(mapPf); mapGo.name = "__WL814b_Map"; mapGo.hideFlags = UnityEngine.HideFlags.HideAndDontSave; }
+ L("맵 " + (mapGo == null ? "실패" : mapGo.name + " renderers=" + mapGo.GetComponentsInChildren(true).Length));
+
+ // 지면 y 찾기 + 소품이 가장 많은 앵커 고르기(룩 캡처라 배경이 비어 있으면 안 된다)
+ UnityEngine.Physics.SyncTransforms();
+ var rends = mapGo == null ? new UnityEngine.Renderer[0] : mapGo.GetComponentsInChildren(true);
+ // 소품이 실제로 모여 있는 곳을 찾는다 — 소품 중심들 중 반경 10 m 이웃이 가장 많은 지점
+ var cands = new System.Collections.Generic.List();
+ for (int r = 0; r < rends.Length; r++)
+ {
+ if (rends[r] == null) continue;
+ var b = rends[r].bounds;
+ if (b.size.y < 1.0f || b.size.y > 20f) continue; // 지형/바닥/거대 오브젝트 제외
+ if (b.center.y > 6f) continue; // 언덕 위·공중 제외
+ cands.Add(b.center);
+ }
+ UnityEngine.Vector3 pcPos = new UnityEngine.Vector3(139f, 0.8f, -20f);
+ int bestCount = -1;
+ for (int i = 0; i < cands.Count; i++)
+ {
+ int n = 0;
+ for (int j = 0; j < cands.Count; j++)
+ if ((cands[j] - cands[i]).sqrMagnitude < 100f) n++; // 반경 10 m
+ if (n > bestCount) { bestCount = n; pcPos = cands[i]; }
+ }
+ string bestHit = "미검출";
+ UnityEngine.RaycastHit gh;
+ if (UnityEngine.Physics.Raycast(new UnityEngine.Vector3(pcPos.x, pcPos.y + 100f, pcPos.z), UnityEngine.Vector3.down, out gh, 400f))
+ { pcPos.y = gh.point.y; bestHit = gh.collider.name; }
+ L(" 소품 후보 " + cands.Count + "개 · 가장 밀집한 지점 반경 10 m 이웃 " + bestCount + "개");
+ L("PC 위치 " + pcPos.ToString("F2") + " · 반경 10 m 소품 " + bestCount + "개 (지면 " + bestHit + ")");
+
+ var pcPf = UnityEditor.AssetDatabase.LoadAssetAtPath(kPc);
+ if (pcPf != null)
+ {
+ pcGo = UnityEngine.Object.Instantiate(pcPf);
+ pcGo.name = "__WL814b_PC";
+ pcGo.hideFlags = UnityEngine.HideFlags.HideAndDontSave;
+ pcGo.transform.position = pcPos;
+ pcGo.transform.rotation = UnityEngine.Quaternion.Euler(0f, 200f, 0f);
+ StripBehaviours(pcGo);
+ L("PC 포즈: " + PoseIdle(pcGo));
+ }
+ L("PC " + (pcGo == null ? "실패" : "ok"));
+
+ // 잡몹 3
+ string[] mobPaths = {
+ "Assets/Res_Addr/Mobs/Mob/Anto_A.prefab",
+ "Assets/Res_Addr/Mobs/Mob/Anto_B.prefab",
+ "Assets/Res_Addr/Mobs/Mob/Angez_A.prefab",
+ };
+ UnityEngine.Vector3[] mobOff = {
+ new UnityEngine.Vector3(2.2f, 0f, 1.6f),
+ new UnityEngine.Vector3(-2.4f, 0f, 0.8f),
+ new UnityEngine.Vector3(0.2f, 0f, 3.0f),
+ };
+ for (int i = 0; i < mobPaths.Length; i++)
+ {
+ var pf = UnityEditor.AssetDatabase.LoadAssetAtPath(mobPaths[i]);
+ if (pf == null) continue;
+ var g = UnityEngine.Object.Instantiate(pf);
+ g.name = "__WL814b_Mob" + i;
+ g.hideFlags = UnityEngine.HideFlags.HideAndDontSave;
+ var p = pcPos + mobOff[i];
+ UnityEngine.RaycastHit mh;
+ if (UnityEngine.Physics.Raycast(new UnityEngine.Vector3(p.x, 200f, p.z), UnityEngine.Vector3.down, out mh, 500f)) p.y = mh.point.y;
+ g.transform.position = p;
+ g.transform.rotation = UnityEngine.Quaternion.Euler(0f, 20f + i * 90f, 0f);
+ StripBehaviours(g);
+ PoseIdle(g);
+ mobs.Add(g);
+ }
+ L("잡몹 " + mobs.Count + "체");
+
+ lightGo = new UnityEngine.GameObject("__WL814b_Sun");
+ lightGo.hideFlags = UnityEngine.HideFlags.HideAndDontSave;
+ var lt = lightGo.AddComponent();
+ lt.type = UnityEngine.LightType.Directional;
+ lt.intensity = 1.1f;
+ lt.color = new UnityEngine.Color(1f, 0.97f, 0.92f);
+ lightGo.transform.rotation = UnityEngine.Quaternion.Euler(48f, 35f, 0f);
+
+ // 원본 카메라 인스턴스 — 811o 구도(h 76 · d 3.0 · up 2.4)를 RealCamera 수식으로 직접 계산
+ var camPf = UnityEditor.AssetDatabase.LoadAssetAtPath(kCam);
+ if (camPf == null) return;
+ camGo = UnityEngine.Object.Instantiate(camPf);
+ camGo.name = "__WL814b_MainCamera";
+ camGo.hideFlags = UnityEngine.HideFlags.HideAndDontSave;
+ StripBehaviours(camGo); // RealCamera·MeshRendererVisibility 정지(트랜스폼은 우리가 잡는다)
+ var cam = camGo.GetComponent();
+ cam.aspect = (float)W / H;
+
+ const float camHeight = 76f, rotateAround = 347.21f, distanceAway = 3.0f, distanceUp = 2.4f;
+ var lookAt = new UnityEngine.Vector3(0f, 1.06f, 0f);
+ var rotv = UnityEngine.Quaternion.Euler(camHeight, rotateAround, 0f) * UnityEngine.Vector3.one;
+ var camPosition = pcPos + UnityEngine.Vector3.up * distanceUp - rotv * distanceAway;
+ camGo.transform.position = camPosition;
+ s_lookAtWorld = pcPos + lookAt;
+ camGo.transform.LookAt(s_lookAtWorld);
+ float dist = UnityEngine.Vector3.Distance(camPosition, pcPos + lookAt);
+ L("카메라(811o 구도) pos=" + camPosition.ToString("F3") + " euler=" + camGo.transform.eulerAngles.ToString("F2"));
+ L(" PC 주시점까지 거리 = " + dist.ToString("F3") + " m → 원근 fov 60 의 반높이 = " + (dist * UnityEngine.Mathf.Tan(30f * UnityEngine.Mathf.Deg2Rad)).ToString("F3") + " m");
+ }
+
+ /// 에디트 모드에서는 Animator 가 돌지 않아 T 포즈가 된다 → idle 클립을 1프레임 샘플링한다.
+ static string PoseIdle(UnityEngine.GameObject go)
+ {
+ var anim = go.GetComponentInChildren(true);
+ if (anim == null || anim.runtimeAnimatorController == null) return "Animator 없음(T 포즈)";
+ var clips = anim.runtimeAnimatorController.animationClips;
+ if (clips == null || clips.Length == 0) return "클립 0(T 포즈)";
+ UnityEngine.AnimationClip pick = null;
+ for (int i = 0; i < clips.Length; i++)
+ {
+ if (clips[i] == null) continue;
+ var n = clips[i].name.ToLower();
+ if (n.Contains("idle") || n.Contains("wait") || n.Contains("stand")) { pick = clips[i]; break; }
+ }
+ if (pick == null) pick = clips[0];
+ pick.SampleAnimation(anim.gameObject, 0.4f);
+ return pick.name + " @0.4s (" + clips.Length + "클립)";
+ }
+
+ /// 임시 씬에서 원본 로직이 돌지 않게 MonoBehaviour 를 전부 끈다(에셋 무변경 · 인스턴스만).
+ static void StripBehaviours(UnityEngine.GameObject go)
+ {
+ var all = go.GetComponentsInChildren(true);
+ for (int i = 0; i < all.Length; i++)
+ {
+ if (all[i] == null) continue;
+ if (all[i] is UnityEngine.Rendering.Universal.UniversalAdditionalCameraData) continue;
+ try { all[i].enabled = false; } catch { }
+ }
+ }
+
+ // ── B/C/D. 조립 · 복원 · 매핑 오차 ──────────────────────────────────────
+ static void SectionBCD(UnityEngine.Camera cam, UnityEngine.GameObject pcGo)
+ {
+ L("");
+ L("## B. 리그 조립");
+ var cfg = MakeCfg(3.8f, 480, false);
+ if (cfg == null) { L("FAIL SO/프리팹 없음 — 중단"); fail++; return; }
+
+ string before = WL.PixelArt.PixelCameraRig.CurrentSummary(cam);
+ int origMask = cam.cullingMask;
+ L("조립 전 원본 카메라: " + before);
+
+ bool ok = WL.PixelArt.PixelCameraRig.Assemble(cfg, cam);
+ Chk(ok && WL.PixelArt.PixelCameraRig.IsAssembled, "조립 성공", WL.PixelArt.PixelCameraRig.LastLog);
+ if (!ok) return;
+
+ var rig = WL.PixelArt.PixelCameraRig.RigRoot;
+ var gameCam = WL.PixelArt.PixelCameraRig.GameCamera;
+ var viewCam = WL.PixelArt.PixelCameraRig.ViewCamera;
+ var mgr = WL.PixelArt.PixelCameraRig.Manager;
+ var proxy = WL.PixelArt.PixelCameraRig.Proxy;
+
+ L("리그 구조:");
+ Dump(rig.transform, 1);
+ L("프록시: " + (proxy == null ? "null" : proxy.name + " parent=" + (proxy.parent == null ? "none" : proxy.parent.name)
+ + " worldPos=" + proxy.position.ToString("F4") + " camPos=" + cam.transform.position.ToString("F4")));
+ Chk(proxy != null && (proxy.position - cam.transform.position).sqrMagnitude < 1e-8f,
+ "프록시 월드 위치 == 원본 카메라 위치(지연 0)", "");
+ Chk(proxy != null && UnityEngine.Quaternion.Angle(proxy.rotation, cam.transform.rotation) < 1e-3f,
+ "프록시 회전 == 원본 카메라 회전", "");
+
+ string after = WL.PixelArt.PixelCameraRig.CurrentSummary(cam);
+ L("조립 후 원본 카메라: " + after);
+ Chk(cam.orthographic, "원본 카메라 직교 전환", "size=" + cam.orthographicSize);
+ Chk(cam.cullingMask == 0, "원본 카메라 월드 미렌더(cullingMask 0)", "mask=" + cam.cullingMask);
+ Chk(cam.tag == "MainCamera" && cam.enabled, "MainCamera 태그·enabled 유지(Camera.main 보존)", "tag=" + cam.tag);
+
+ // Critter 를 1프레임 강제로 돌린다(에디트 모드에는 LateUpdate 가 안 올 수 있다)
+ viewCam.aspect = (float)W / H;
+ mgr.SendMessage("LateUpdate", UnityEngine.SendMessageOptions.DontRequireReceiver);
+
+ var rt = gameCam.targetTexture;
+ L("게임 카메라: ortho=" + gameCam.orthographic + " size=" + gameCam.orthographicSize.ToString("F4")
+ + " mask=" + gameCam.cullingMask + " depth=" + gameCam.depth
+ + " RT=" + (rt == null ? "null" : rt.width + "×" + rt.height + " filter=" + rt.filterMode + " fmt=" + rt.format));
+ L("뷰 카메라: ortho=" + viewCam.orthographic + " size=" + viewCam.orthographicSize.ToString("F4")
+ + " mask=" + viewCam.cullingMask + " near=" + viewCam.nearClipPlane + " far=" + viewCam.farClipPlane
+ + " localPos=" + viewCam.transform.localPosition.ToString("F5"));
+ L("Critter: GameResolution=" + mgr.GameResolution + " zoom=" + mgr.GameCameraZoom.ToString("F5")
+ + " viewZoom=" + mgr.ViewCameraZoom + " grid=" + mgr.VoxelGridMovement + " sub=" + mgr.SubpixelAdjustments
+ + " followRot=" + mgr.FollowRotation);
+ Chk(rt != null && rt.height == 480 && rt.filterMode == UnityEngine.FilterMode.Point,
+ "저해상도 RT 480줄 · 포인트 필터", rt == null ? "null" : rt.width + "×" + rt.height);
+ Chk(gameCam.cullingMask == (origMask & ~(1 << cfg.rigLayer)),
+ "게임 카메라 = 원본 cullingMask 승계", "orig=" + origMask + " game=" + gameCam.cullingMask);
+ Chk((gameCam.cullingMask & (1 << cfg.rigLayer)) == 0, "게임 카메라가 픽셀 쿼드를 다시 그리지 않는다(리그 레이어 제외)", "");
+ Chk(viewCam.cullingMask == (1 << cfg.rigLayer), "뷰 카메라는 픽셀 쿼드만 그린다", "mask=" + viewCam.cullingMask);
+
+ // ── D. 매핑 오차
+ L("");
+ L("## D. 매핑 오차 — Camera.main 투영 vs 실제 화면(1080×1920 · px)");
+ MappingTable(cam, gameCam, viewCam, mgr, pcGo);
+
+ // ── C. 복원
+ L("");
+ L("## C. 복원");
+ var rtRef = gameCam.targetTexture;
+ WL.PixelArt.PixelCameraRig.Teardown("probe C");
+ string restored = WL.PixelArt.PixelCameraRig.CurrentSummary(cam);
+ L("복원 후 원본 카메라: " + restored);
+ Chk(restored == before, "원본 카메라 값 스냅샷 == 복원값(문자열 완전 일치)", restored == before ? "" : "\n before=" + before + "\n after =" + restored);
+ Chk(!WL.PixelArt.PixelCameraRig.IsAssembled, "리그 오브젝트 0", "");
+ Chk(rtRef == null, "RT 참조 해제(Release + Destroy)", "rt=" + (rtRef == null ? "null" : "alive"));
+ int strays = 0;
+ var left = UnityEngine.Object.FindObjectsByType(UnityEngine.FindObjectsInactive.Include, UnityEngine.FindObjectsSortMode.None);
+ strays = left == null ? 0 : left.Length;
+ Chk(strays == 0, "씬에 PixelCameraManager 잔재 0", "found=" + strays);
+ int proxyLeft = 0;
+ for (int i = 0; i < cam.transform.childCount; i++) if (cam.transform.GetChild(i).name == WL.PixelArt.PixelCameraRig.ProxyName) proxyLeft++;
+ Chk(proxyLeft == 0, "원본 카메라 자식 프록시 0", "found=" + proxyLeft);
+
+ var mat = UnityEditor.AssetDatabase.LoadAssetAtPath("Assets/3DPixelCamera/URP/UpscaleMaterialURP.mat");
+ bool matClean = mat == null || !mat.HasProperty("_LowResTexture") || mat.GetTexture("_LowResTexture") == null;
+ Chk(matClean, "디스크 UpscaleMaterialURP.mat 의 _LowResTexture 오염 0(런타임 인스턴스 사용)",
+ mat == null ? "mat=null" : ("tex=" + (mat.GetTexture("_LowResTexture") == null ? "null" : mat.GetTexture("_LowResTexture").name)));
+ }
+
+ static void MappingTable(UnityEngine.Camera src, UnityEngine.Camera gameCam, UnityEngine.Camera viewCam,
+ PixelCamera.PixelCameraManager mgr, UnityEngine.GameObject pcGo)
+ {
+ var quad = FindQuad();
+ if (quad == null) { L("FAIL 픽셀 쿼드를 못 찾음"); fail++; return; }
+ var rt = gameCam.targetTexture;
+ if (rt == null) { L("FAIL RT 없음"); fail++; return; }
+
+ var basePos = pcGo != null ? pcGo.transform.position : src.transform.position + src.transform.forward * 6f;
+ var pts = new UnityEngine.Vector3[]
+ {
+ basePos,
+ basePos + new UnityEngine.Vector3(0f, 1.7f, 0f),
+ basePos + new UnityEngine.Vector3(1.8f, 0.2f, 1.4f),
+ basePos + new UnityEngine.Vector3(-2.1f, 1.0f, 1.0f),
+ basePos + new UnityEngine.Vector3(0.4f, 0.6f, 2.6f),
+ };
+
+ L(" # | world | Camera.main px | 실제 화면 px | 오차 px | RT양자화 포함 오차 px");
+ float maxErr = 0f, maxErrQ = 0f, sumErr = 0f, sumErrQ = 0f;
+ for (int i = 0; i < pts.Length; i++)
+ {
+ var p = pts[i];
+ var vSrc = src.WorldToViewportPoint(p);
+ var expect = new UnityEngine.Vector2(vSrc.x * W, vSrc.y * H);
+
+ var vGame = gameCam.WorldToViewportPoint(p);
+ var actual = ViewportToScreen(vGame.x, vGame.y, quad, viewCam);
+
+ float qx = (UnityEngine.Mathf.Floor(vGame.x * rt.width) + 0.5f) / rt.width;
+ float qy = (UnityEngine.Mathf.Floor(vGame.y * rt.height) + 0.5f) / rt.height;
+ var actualQ = ViewportToScreen(qx, qy, quad, viewCam);
+
+ float e = UnityEngine.Vector2.Distance(expect, actual);
+ float eq = UnityEngine.Vector2.Distance(expect, actualQ);
+ maxErr = UnityEngine.Mathf.Max(maxErr, e); maxErrQ = UnityEngine.Mathf.Max(maxErrQ, eq);
+ sumErr += e; sumErrQ += eq;
+ L(" " + (i + 1) + " | " + p.ToString("F2")
+ + " | (" + expect.x.ToString("F1") + "," + expect.y.ToString("F1") + ")"
+ + " | (" + actual.x.ToString("F1") + "," + actual.y.ToString("F1") + ")"
+ + " | " + e.ToString("F2")
+ + " | " + eq.ToString("F2"));
+ }
+ L(" 최대 " + maxErr.ToString("F2") + " px · 평균 " + (sumErr / pts.Length).ToString("F2")
+ + " px (연속) / 최대 " + maxErrQ.ToString("F2") + " px · 평균 " + (sumErrQ / pts.Length).ToString("F2") + " px (RT 양자화 포함)");
+ L(" 참고: 1 RT 픽셀 = 화면 " + ((float)H / rt.height).ToString("F2") + " px(세로) · " + ((float)W / rt.width).ToString("F2") + " px(가로)");
+ Chk(maxErr <= 2.0f, "연속 매핑 오차 ≤ 2 px (compensateViewZoom 보정 확인)", "max=" + maxErr.ToString("F2") + " px");
+ Chk(maxErrQ <= (float)H / rt.height, "RT 양자화 포함 오차 ≤ 업스케일 1픽셀", "max=" + maxErrQ.ToString("F2") + " px");
+ }
+
+ static UnityEngine.Vector2 ViewportToScreen(float vx, float vy, UnityEngine.Transform quad, UnityEngine.Camera viewCam)
+ {
+ var quadLocal = new UnityEngine.Vector3(vx - 0.5f, vy - 0.5f, 0f);
+ var quadWorld = quad.TransformPoint(quadLocal);
+ var vView = viewCam.WorldToViewportPoint(quadWorld);
+ return new UnityEngine.Vector2(vView.x * W, vView.y * H);
+ }
+
+ static UnityEngine.Transform FindQuad()
+ {
+ var rig = WL.PixelArt.PixelCameraRig.RigRoot;
+ if (rig == null) return null;
+ var uc = rig.GetComponentInChildren(true);
+ return uc == null ? null : uc.transform;
+ }
+
+ static void Dump(UnityEngine.Transform t, int depth)
+ {
+ var line = new System.Text.StringBuilder();
+ line.Append(' ', depth * 2).Append("- ").Append(t.name).Append(" layer=").Append(t.gameObject.layer);
+ var comps = t.GetComponents();
+ line.Append(" [");
+ for (int i = 0; i < comps.Length; i++) if (comps[i] != null) line.Append(comps[i].GetType().Name).Append(' ');
+ line.Append("]");
+ line.Append(" lp=").Append(t.localPosition.ToString("F4")).Append(" ls=").Append(t.localScale.ToString("F4"));
+ L(line.ToString());
+ for (int i = 0; i < t.childCount; i++) Dump(t.GetChild(i), depth + 1);
+ }
+
+ // ── E. GC ────────────────────────────────────────────────────────────────
+ static void SectionE(UnityEngine.Camera cam)
+ {
+ L("");
+ L("## E. GC (200k 회)");
+ var probeGo = new UnityEngine.GameObject("__WL814b_MirrorProbe");
+ probeGo.hideFlags = UnityEngine.HideFlags.HideAndDontSave;
+ var mirror = probeGo.AddComponent();
+ mirror.Source = cam.transform;
+
+ System.GC.Collect();
+ long m0 = System.GC.GetAllocatedBytesForCurrentThread();
+ long t0 = System.GC.GetTotalMemory(false);
+ int g0 = System.GC.CollectionCount(0);
+ for (int i = 0; i < 200000; i++) mirror.Mirror();
+ long m1 = System.GC.GetAllocatedBytesForCurrentThread();
+ long t1 = System.GC.GetTotalMemory(false);
+ int g1 = System.GC.CollectionCount(0);
+ L("프록시 미러 ×200k: thread Δ" + (m1 - m0) + " B · total Δ" + (t1 - t0) + " B · gen0 " + (g1 - g0));
+ Chk(m1 - m0 == 0, "프록시 미러 GC 0 B", "Δ=" + (m1 - m0));
+ UnityEngine.Object.DestroyImmediate(probeGo);
+
+ var cfg = MakeCfg(3.8f, 480, false);
+ WL.PixelArt.PixelCameraRig.Assemble(cfg, cam);
+ System.GC.Collect();
+ long s0 = System.GC.GetAllocatedBytesForCurrentThread();
+ for (int i = 0; i < 200000; i++) WL.PixelArt.PixelCameraRig.ProbeSnapTick();
+ long s1 = System.GC.GetAllocatedBytesForCurrentThread();
+ L("회전 스냅 판정 ×200k: thread Δ" + (s1 - s0) + " B");
+ Chk(s1 - s0 == 0, "회전 스냅 판정 GC 0 B", "Δ=" + (s1 - s0));
+ WL.PixelArt.PixelCameraRig.Teardown("probe E");
+ }
+
+ // ── F. C8 ────────────────────────────────────────────────────────────────
+ static void SectionF(UnityEngine.Camera cam)
+ {
+ L("");
+ L("## F. C8 롤백");
+ var so = WL.PixelArt.WLPixelCameraSettings.Instance;
+ Chk(so != null, "SO 로드(Resources/WL/WLPixelCameraSettings)", so == null ? "null" : "enabled=" + so.enabled);
+
+ string before = WL.PixelArt.PixelCameraRig.CurrentSummary(cam);
+ var cfg = MakeCfg(3.8f, 480, false);
+ WL.PixelArt.PixelCameraRig.Assemble(cfg, cam);
+ Chk(WL.PixelArt.PixelCameraRig.IsAssembled, "조립됨(C8 전)", "");
+
+ WL.PixelArt.WLPixelCameraSettings.RuntimeDisabled = true;
+ Chk(!WL.PixelArt.WLPixelCameraSettings.Enabled, "RuntimeDisabled → Enabled=false", "");
+ WL.PixelArt.PixelCameraRig.Tick(); // Active=false → 즉시 Teardown
+ Chk(!WL.PixelArt.PixelCameraRig.IsAssembled, "Tick 1회에 리그 해체", "");
+ string after = WL.PixelArt.PixelCameraRig.CurrentSummary(cam);
+ Chk(after == before, "C8 복원값 == 원값", after == before ? "" : "\n before=" + before + "\n after =" + after);
+
+ WL.PixelArt.PixelCameraRig.Tick(); // 재호출해도 조립 0
+ Chk(!WL.PixelArt.PixelCameraRig.IsAssembled, "C8 상태에서 재조립 0", "");
+ WL.PixelArt.WLPixelCameraSettings.RuntimeDisabled = false;
+ }
+
+ // ── G. 캡처 ──────────────────────────────────────────────────────────────
+ static void SectionG(UnityEngine.Camera cam)
+ {
+ L("");
+ L("## G. 룩 캡처 1080×1920 → " + kOutDir);
+ L(CaptureControl(cam, "look_00_persp_original"));
+ L(CaptureRig(cam, 3.8f, 480, "look_01_ortho38_px480"));
+ L(CaptureRig(cam, 3.8f, 360, "look_02_ortho38_px360"));
+ L(CaptureRig(cam, 4.6f, 480, "look_03_ortho46_px480"));
+ // 보너스 — 811o 구도의 실측 거리(카메라→주시점)에서 원근 fov 60 과 PC 평면 크기가 정확히 같아지는 ortho
+ float matched = UnityEngine.Vector3.Distance(cam.transform.position, s_lookAtWorld) * UnityEngine.Mathf.Tan(30f * UnityEngine.Mathf.Deg2Rad);
+ L(CaptureRig(cam, matched, 480, "look_04_orthoMatched_px480") + " ← 실측 정합값 ortho " + matched.ToString("F3"));
+ }
+
+ static string CaptureControl(UnityEngine.Camera cam, string tag)
+ {
+ var rt = new UnityEngine.RenderTexture(W, H, 24, UnityEngine.RenderTextureFormat.ARGB32);
+ var prevTarget = cam.targetTexture;
+ float prevAspect = cam.aspect;
+ cam.aspect = (float)W / H;
+ cam.targetTexture = rt;
+ cam.Render();
+ cam.targetTexture = prevTarget;
+ cam.aspect = prevAspect;
+ string path = WritePng(rt, tag);
+ rt.Release(); UnityEngine.Object.DestroyImmediate(rt);
+ return " 대조(원근 fov " + cam.fieldOfView + ") → " + path;
+ }
+
+ static string CaptureRig(UnityEngine.Camera cam, float orthoSize, int pixelHeight, string tag)
+ {
+ var cfg = MakeCfg(orthoSize, pixelHeight, false); // viewCameraInMainStack=false → 뷰 카메라를 Base 로 직접 렌더
+ if (cfg == null) return " FAIL cfg";
+ if (!WL.PixelArt.PixelCameraRig.Assemble(cfg, cam)) return " FAIL assemble " + tag;
+
+ var gameCam = WL.PixelArt.PixelCameraRig.GameCamera;
+ var viewCam = WL.PixelArt.PixelCameraRig.ViewCamera;
+ var mgr = WL.PixelArt.PixelCameraRig.Manager;
+
+ var cap = new UnityEngine.RenderTexture(W, H, 24, UnityEngine.RenderTextureFormat.ARGB32);
+ viewCam.aspect = (float)W / H;
+ viewCam.targetTexture = cap;
+ mgr.SendMessage("LateUpdate", UnityEngine.SendMessageOptions.DontRequireReceiver);
+ mgr.SendMessage("LateUpdate", UnityEngine.SendMessageOptions.DontRequireReceiver); // RT 생성 후 위치·줌 확정
+
+ var lowRt = gameCam.targetTexture;
+ gameCam.Render(); // 저해상도 RT 를 채운다
+ viewCam.Render(); // 쿼드를 1080×1920 으로 업스케일
+
+ string path = WritePng(cap, tag);
+ string info = " ortho " + orthoSize.ToString("0.##") + " × px " + pixelHeight
+ + " → RT " + (lowRt == null ? "null" : lowRt.width + "×" + lowRt.height)
+ + " · gameZoom " + mgr.GameCameraZoom.ToString("F4")
+ + " · viewSize " + viewCam.orthographicSize.ToString("F4")
+ + " → " + path;
+
+ viewCam.targetTexture = null;
+ cap.Release(); UnityEngine.Object.DestroyImmediate(cap);
+ WL.PixelArt.PixelCameraRig.Teardown("capture " + tag);
+ return info;
+ }
+
+ static string WritePng(UnityEngine.RenderTexture rt, string tag)
+ {
+ var prev = UnityEngine.RenderTexture.active;
+ UnityEngine.RenderTexture.active = rt;
+ var tex = new UnityEngine.Texture2D(rt.width, rt.height, UnityEngine.TextureFormat.RGB24, false);
+ tex.ReadPixels(new UnityEngine.Rect(0, 0, rt.width, rt.height), 0, 0);
+ tex.Apply();
+ UnityEngine.RenderTexture.active = prev;
+ var path = System.IO.Path.Combine(kOutDir, tag + ".png");
+ System.IO.File.WriteAllBytes(path, UnityEngine.ImageConversion.EncodeToPNG(tex));
+ UnityEngine.Object.DestroyImmediate(tex);
+ return path;
+ }
+
+ // ── 임시 설정(디스크 SO 를 절대 건드리지 않는다) ─────────────────────────
+ static WL.PixelArt.WLPixelCameraSettings MakeCfg(float orthoSize, int pixelHeight, bool inStack)
+ {
+ var rig = UnityEditor.AssetDatabase.LoadAssetAtPath(kRig);
+ if (rig == null) return null;
+ var cfg = UnityEngine.ScriptableObject.CreateInstance();
+ cfg.hideFlags = UnityEngine.HideFlags.HideAndDontSave;
+ cfg.pixelCameraSystemPrefab = rig;
+ cfg.orthoSize = orthoSize;
+ cfg.pixelHeight = pixelHeight;
+ cfg.viewCameraInMainStack = inStack;
+ cfg.verboseLog = false;
+ return cfg;
+ }
+}
diff --git a/AgentScripts/staging/WL814b/EDIT_PROBE.txt b/AgentScripts/staging/WL814b/EDIT_PROBE.txt
new file mode 100644
index 000000000..e4915207a
--- /dev/null
+++ b/AgentScripts/staging/WL814b/EDIT_PROBE.txt
@@ -0,0 +1,94 @@
+# WL-814b 프로브 — 2026-09-10 23:27:24
+unity=6000.3.23f1 · isPlaying=False
+
+## A. 원본 카메라 · UI 캔버스 실측
+Main Camera.prefab: tag=MainCamera layer=0 parent=none children=0
+ Camera: ortho=False fov=60 size=5 near=0.3 far=1000 depth=5 mask=95 clear=Skybox hdr=True msaa=True occlusionCulling=False
+ URP: type=Base post=True shadows=False volumeMask=1 aa=None stack=0
+ 컴포넌트: RealCamera=True AudioListener=True MeshRendererVisibility=False
+ PASS 원본 카메라 = RealCamera + AudioListener 보유(재부모화·비활성 금지 근거)
+NewGameUI.prefab 캔버스 1개
+ [0] NewGameUI renderMode=ScreenSpaceCamera worldCamera=Camera planeDistance=100 sortingOrder=0 layer=5
+ UI camera: Camera ortho=True depth=6 mask=32 clear=Nothing
+ PASS 인게임 UI 캔버스 = Screen Space - Camera(UICamera) → 원본 카메라를 끄면 UI 가 사라진다
+현재 씬 = '' path='' dirty(before)=False rootCount=0
+
+## B. 임시 씬(추가 로드 · 저장 0)
+맵 __WL814b_Map renderers=1299
+ 소품 후보 799개 · 가장 밀집한 지점 반경 10 m 이웃 36개
+PC 위치 (192.32, 1.99, -46.40) · 반경 10 m 소품 36개 (지면 Collider)
+PC 포즈: Idle @0.4s (26클립)
+PC ok
+잡몹 3체
+카메라(811o 구도) pos=(190.198, 6.579, -50.608) euler=(36.79, 26.73, 0.00)
+ PC 주시점까지 거리 = 5.887 m → 원근 fov 60 의 반높이 = 3.399 m
+
+## B. 리그 조립
+조립 전 원본 카메라: ortho=0 size=5 fov=60 near=0.3 far=1000 depth=5 mask=95 clear=1 bg=0,0,0,1 hdr=1 msaa=1 occ=0 rt=0 type=0 post=1 shadow=0 vmask=1 aa=0 stack=0
+ PASS 조립 성공 조립 — ortho 3.8 · RT 640×480 · zoom 3.8159 · layer 31
+리그 구조:
+ - WL_PixelCameraRig layer=31 [Transform ] lp=(190.1982, 6.5791, -50.6082) ls=(1.0000, 1.0000, 1.0000)
+ - PixelCameraTransform layer=31 [Transform ] lp=(0.0000, 0.0000, 0.0000) ls=(1.0000, 1.0000, 1.0000)
+ - PixelCamera layer=31 [Transform Camera PixelCameraManager UniversalAdditionalCameraData ] lp=(0.0000, 0.0000, 0.0000) ls=(1.0000, 1.0000, 1.0000)
+ - UpscaledDisplay layer=31 [Transform ] lp=(0.0000, 0.0000, -1.0000) ls=(1.0000, 1.0000, 1.0000)
+ - ViewCamera layer=31 [Transform Camera UniversalAdditionalCameraData CanvasViewCamera ] lp=(0.0000, 0.0086, -1.0000) ls=(1.0000, 1.0000, 1.0000)
+ - QuadCanvas layer=31 [Transform MeshFilter MeshRenderer UpscaledCanvas ] lp=(0.0000, 0.0000, 0.0000) ls=(19.8022, 10.0556, 1.0000)
+프록시: WL_PixelFollow parent=__WL814b_MainCamera worldPos=(190.1982, 6.5791, -50.6082) camPos=(190.1982, 6.5791, -50.6082)
+ PASS 프록시 월드 위치 == 원본 카메라 위치(지연 0)
+ PASS 프록시 회전 == 원본 카메라 회전
+조립 후 원본 카메라: ortho=1 size=3.8 fov=60 near=0.3 far=1000 depth=5 mask=0 clear=2 bg=0,0,0,1 hdr=1 msaa=1 occ=0 rt=0 type=0 post=0 shadow=0 vmask=1 aa=0 stack=0
+ PASS 원본 카메라 직교 전환 size=3.8
+ PASS 원본 카메라 월드 미렌더(cullingMask 0) mask=0
+ PASS MainCamera 태그·enabled 유지(Camera.main 보존) tag=MainCamera
+게임 카메라: ortho=True size=3.8159 mask=95 depth=4 RT=270×480 filter=Point fmt=ARGB32
+뷰 카메라: ortho=True size=3.8000 mask=-2147483648 near=0 far=1001 localPos=(-0.00383, 0.00197, -1.00000)
+Critter: GameResolution=(270, 480) zoom=3.81590 viewZoom=1 grid=True sub=True followRot=True
+ PASS 저해상도 RT 480줄 · 포인트 필터 270×480
+ PASS 게임 카메라 = 원본 cullingMask 승계 orig=95 game=95
+ PASS 게임 카메라가 픽셀 쿼드를 다시 그리지 않는다(리그 레이어 제외)
+ PASS 뷰 카메라는 픽셀 쿼드만 그린다 mask=-2147483648
+
+## D. 매핑 오차 — Camera.main 투영 vs 실제 화면(1080×1920 · px)
+ # | world | Camera.main px | 실제 화면 px | 오차 px | RT양자화 포함 오차 px
+ 1 | (192.32, 1.99, -46.40) | (540.0,745.5) | (540.0,745.5) | 0.00 | 1.40
+ 2 | (192.32, 3.69, -46.40) | (540.0,1089.5) | (540.0,1089.5) | 0.00 | 1.19
+ 3 | (194.12, 2.19, -45.00) | (787.1,1097.7) | (787.1,1097.7) | 0.00 | 1.03
+ 4 | (190.22, 2.99, -45.40) | (-47.5,940.1) | (-47.5,940.1) | 0.00 | 1.35
+ 5 | (192.72, 2.59, -43.80) | (334.8,1245.5) | (334.8,1245.5) | 0.00 | 1.43
+ 최대 0.00 px · 평균 0.00 px (연속) / 최대 1.43 px · 평균 1.28 px (RT 양자화 포함)
+ 참고: 1 RT 픽셀 = 화면 4.00 px(세로) · 4.00 px(가로)
+ PASS 연속 매핑 오차 ≤ 2 px (compensateViewZoom 보정 확인) max=0.00 px
+ PASS RT 양자화 포함 오차 ≤ 업스케일 1픽셀 max=1.43 px
+
+## C. 복원
+복원 후 원본 카메라: ortho=0 size=5 fov=60 near=0.3 far=1000 depth=5 mask=95 clear=1 bg=0,0,0,1 hdr=1 msaa=1 occ=0 rt=0 type=0 post=1 shadow=0 vmask=1 aa=0 stack=0
+ PASS 원본 카메라 값 스냅샷 == 복원값(문자열 완전 일치)
+ PASS 리그 오브젝트 0
+ PASS RT 참조 해제(Release + Destroy) rt=null
+ PASS 씬에 PixelCameraManager 잔재 0 found=0
+ PASS 원본 카메라 자식 프록시 0 found=0
+ PASS 디스크 UpscaleMaterialURP.mat 의 _LowResTexture 오염 0(런타임 인스턴스 사용) tex=null
+
+## E. GC (200k 회)
+프록시 미러 ×200k: thread Δ0 B · total Δ0 B · gen0 0
+ PASS 프록시 미러 GC 0 B Δ=0
+회전 스냅 판정 ×200k: thread Δ0 B
+ PASS 회전 스냅 판정 GC 0 B Δ=0
+
+## F. C8 롤백
+ PASS SO 로드(Resources/WL/WLPixelCameraSettings) enabled=True
+ PASS 조립됨(C8 전)
+ PASS RuntimeDisabled → Enabled=false
+ PASS Tick 1회에 리그 해체
+ PASS C8 복원값 == 원값
+ PASS C8 상태에서 재조립 0
+
+## G. 룩 캡처 1080×1920 → E:\NerdNavis\nn_himminji\Screenshots_WL\WL814b
+ 대조(원근 fov 60) → E:\NerdNavis\nn_himminji\Screenshots_WL\WL814b\look_00_persp_original.png
+ ortho 3.8 × px 480 → RT 270×480 · gameZoom 3.8159 · viewSize 3.8000 → E:\NerdNavis\nn_himminji\Screenshots_WL\WL814b\look_01_ortho38_px480.png
+ ortho 3.8 × px 360 → RT 202×360 · gameZoom 3.8212 · viewSize 3.8000 → E:\NerdNavis\nn_himminji\Screenshots_WL\WL814b\look_02_ortho38_px360.png
+ ortho 4.6 × px 480 → RT 270×480 · gameZoom 4.6192 · viewSize 4.6000 → E:\NerdNavis\nn_himminji\Screenshots_WL\WL814b\look_03_ortho46_px480.png
+ ortho 3.4 × px 480 → RT 270×480 · gameZoom 3.4128 · viewSize 3.3986 → E:\NerdNavis\nn_himminji\Screenshots_WL\WL814b\look_04_orthoMatched_px480.png ← 실측 정합값 ortho 3.399
+씬 정리 후: dirty=False rootCount=0 (저장 0)
+
+RESULT PASS 28/28
diff --git a/Assets/3DPixelCamera/URP.meta b/Assets/3DPixelCamera/URP.meta
new file mode 100644
index 000000000..b42537d64
--- /dev/null
+++ b/Assets/3DPixelCamera/URP.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 89ba2272d61bfaf4f8e60603c1027381
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/3DPixelCamera/URP/DemoScene.unity b/Assets/3DPixelCamera/URP/DemoScene.unity
new file mode 100644
index 000000000..597f44845
--- /dev/null
+++ b/Assets/3DPixelCamera/URP/DemoScene.unity
@@ -0,0 +1,1226 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!29 &1
+OcclusionCullingSettings:
+ m_ObjectHideFlags: 0
+ serializedVersion: 2
+ m_OcclusionBakeSettings:
+ smallestOccluder: 5
+ smallestHole: 0.25
+ backfaceThreshold: 100
+ m_SceneGUID: 00000000000000000000000000000000
+ m_OcclusionCullingData: {fileID: 0}
+--- !u!104 &2
+RenderSettings:
+ m_ObjectHideFlags: 0
+ serializedVersion: 9
+ m_Fog: 0
+ m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1}
+ m_FogMode: 3
+ m_FogDensity: 0.01
+ m_LinearFogStart: 0
+ m_LinearFogEnd: 300
+ m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1}
+ m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1}
+ m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1}
+ m_AmbientIntensity: 1
+ m_AmbientMode: 0
+ m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1}
+ m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0}
+ m_HaloStrength: 0.5
+ m_FlareStrength: 1
+ m_FlareFadeSpeed: 3
+ m_HaloTexture: {fileID: 0}
+ m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0}
+ m_DefaultReflectionMode: 0
+ m_DefaultReflectionResolution: 128
+ m_ReflectionBounces: 1
+ m_ReflectionIntensity: 1
+ m_CustomReflection: {fileID: 0}
+ m_Sun: {fileID: 0}
+ m_IndirectSpecularColor: {r: 0.18028378, g: 0.22571412, b: 0.30692285, a: 1}
+ m_UseRadianceAmbientProbe: 0
+--- !u!157 &3
+LightmapSettings:
+ m_ObjectHideFlags: 0
+ serializedVersion: 12
+ m_GIWorkflowMode: 1
+ m_GISettings:
+ serializedVersion: 2
+ m_BounceScale: 1
+ m_IndirectOutputScale: 1
+ m_AlbedoBoost: 1
+ m_EnvironmentLightingMode: 0
+ m_EnableBakedLightmaps: 1
+ m_EnableRealtimeLightmaps: 0
+ m_LightmapEditorSettings:
+ serializedVersion: 12
+ m_Resolution: 2
+ m_BakeResolution: 40
+ m_AtlasSize: 1024
+ m_AO: 0
+ m_AOMaxDistance: 1
+ m_CompAOExponent: 1
+ m_CompAOExponentDirect: 0
+ m_ExtractAmbientOcclusion: 0
+ m_Padding: 2
+ m_LightmapParameters: {fileID: 0}
+ m_LightmapsBakeMode: 1
+ m_TextureCompression: 1
+ m_FinalGather: 0
+ m_FinalGatherFiltering: 1
+ m_FinalGatherRayCount: 256
+ m_ReflectionCompression: 2
+ m_MixedBakeMode: 2
+ m_BakeBackend: 1
+ m_PVRSampling: 1
+ m_PVRDirectSampleCount: 32
+ m_PVRSampleCount: 512
+ m_PVRBounces: 2
+ m_PVREnvironmentSampleCount: 256
+ m_PVREnvironmentReferencePointCount: 2048
+ m_PVRFilteringMode: 1
+ m_PVRDenoiserTypeDirect: 1
+ m_PVRDenoiserTypeIndirect: 1
+ m_PVRDenoiserTypeAO: 1
+ m_PVRFilterTypeDirect: 0
+ m_PVRFilterTypeIndirect: 0
+ m_PVRFilterTypeAO: 0
+ m_PVREnvironmentMIS: 1
+ m_PVRCulling: 1
+ m_PVRFilteringGaussRadiusDirect: 1
+ m_PVRFilteringGaussRadiusIndirect: 5
+ m_PVRFilteringGaussRadiusAO: 2
+ m_PVRFilteringAtrousPositionSigmaDirect: 0.5
+ m_PVRFilteringAtrousPositionSigmaIndirect: 2
+ m_PVRFilteringAtrousPositionSigmaAO: 1
+ m_ExportTrainingData: 0
+ m_TrainingDataDestination: TrainingData
+ m_LightProbeSampleCountMultiplier: 4
+ m_LightingDataAsset: {fileID: 0}
+ m_LightingSettings: {fileID: 0}
+--- !u!196 &4
+NavMeshSettings:
+ serializedVersion: 2
+ m_ObjectHideFlags: 0
+ m_BuildSettings:
+ serializedVersion: 3
+ agentTypeID: 0
+ agentRadius: 0.5
+ agentHeight: 2
+ agentSlope: 45
+ agentClimb: 0.4
+ ledgeDropHeight: 0
+ maxJumpAcrossDistance: 0
+ minRegionArea: 2
+ manualCellSize: 0
+ cellSize: 0.16666667
+ manualTileSize: 0
+ tileSize: 256
+ buildHeightMesh: 0
+ maxJobWorkers: 0
+ preserveTilesOutsideBounds: 0
+ debug:
+ m_Flags: 0
+ m_NavMeshData: {fileID: 0}
+--- !u!1 &9044789
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 9044793}
+ - component: {fileID: 9044792}
+ - component: {fileID: 9044791}
+ - component: {fileID: 9044790}
+ m_Layer: 0
+ m_Name: Plane
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!64 &9044790
+MeshCollider:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 9044789}
+ m_Material: {fileID: 0}
+ m_IncludeLayers:
+ serializedVersion: 2
+ m_Bits: 0
+ m_ExcludeLayers:
+ serializedVersion: 2
+ m_Bits: 0
+ m_LayerOverridePriority: 0
+ m_IsTrigger: 0
+ m_ProvidesContacts: 0
+ m_Enabled: 1
+ serializedVersion: 5
+ m_Convex: 0
+ m_CookingOptions: 30
+ m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0}
+--- !u!23 &9044791
+MeshRenderer:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 9044789}
+ m_Enabled: 1
+ m_CastShadows: 1
+ m_ReceiveShadows: 1
+ m_DynamicOccludee: 1
+ m_StaticShadowCaster: 0
+ m_MotionVectors: 1
+ m_LightProbeUsage: 1
+ m_ReflectionProbeUsage: 1
+ m_RayTracingMode: 2
+ m_RayTraceProcedural: 0
+ m_RenderingLayerMask: 1
+ m_RendererPriority: 0
+ m_Materials:
+ - {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, type: 2}
+ m_StaticBatchInfo:
+ firstSubMesh: 0
+ subMeshCount: 0
+ m_StaticBatchRoot: {fileID: 0}
+ m_ProbeAnchor: {fileID: 0}
+ m_LightProbeVolumeOverride: {fileID: 0}
+ m_ScaleInLightmap: 1
+ m_ReceiveGI: 1
+ m_PreserveUVs: 0
+ m_IgnoreNormalsForChartDetection: 0
+ m_ImportantGI: 0
+ m_StitchLightmapSeams: 1
+ m_SelectedEditorRenderState: 3
+ m_MinimumChartSize: 4
+ m_AutoUVMaxDistance: 0.5
+ m_AutoUVMaxAngle: 89
+ m_LightmapParameters: {fileID: 0}
+ m_SortingLayerID: 0
+ m_SortingLayer: 0
+ m_SortingOrder: 0
+ m_AdditionalVertexStreams: {fileID: 0}
+--- !u!33 &9044792
+MeshFilter:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 9044789}
+ m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0}
+--- !u!4 &9044793
+Transform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 9044789}
+ m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
+ m_LocalPosition: {x: 0, y: 0, z: 0}
+ m_LocalScale: {x: 2, y: 2, z: 2}
+ m_ConstrainProportionsScale: 0
+ m_Children: []
+ m_Father: {fileID: 1086287180}
+ m_RootOrder: -1
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!1 &117850981
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 117850982}
+ - component: {fileID: 117850985}
+ - component: {fileID: 117850984}
+ - component: {fileID: 117850983}
+ - component: {fileID: 117850986}
+ m_Layer: 0
+ m_Name: Cube (1)
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!4 &117850982
+Transform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 117850981}
+ m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+ m_LocalPosition: {x: -3.85, y: 0.194, z: 1.02}
+ m_LocalScale: {x: 2, y: 2, z: 2}
+ m_ConstrainProportionsScale: 0
+ m_Children: []
+ m_Father: {fileID: 1086287180}
+ m_RootOrder: -1
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!65 &117850983
+BoxCollider:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 117850981}
+ m_Material: {fileID: 0}
+ m_IncludeLayers:
+ serializedVersion: 2
+ m_Bits: 0
+ m_ExcludeLayers:
+ serializedVersion: 2
+ m_Bits: 0
+ m_LayerOverridePriority: 0
+ m_IsTrigger: 0
+ m_ProvidesContacts: 0
+ m_Enabled: 1
+ serializedVersion: 3
+ m_Size: {x: 1, y: 1, z: 1}
+ m_Center: {x: 0, y: 0, z: 0}
+--- !u!23 &117850984
+MeshRenderer:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 117850981}
+ m_Enabled: 1
+ m_CastShadows: 1
+ m_ReceiveShadows: 1
+ m_DynamicOccludee: 1
+ m_StaticShadowCaster: 0
+ m_MotionVectors: 1
+ m_LightProbeUsage: 1
+ m_ReflectionProbeUsage: 1
+ m_RayTracingMode: 2
+ m_RayTraceProcedural: 0
+ m_RenderingLayerMask: 1
+ m_RendererPriority: 0
+ m_Materials:
+ - {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, type: 2}
+ m_StaticBatchInfo:
+ firstSubMesh: 0
+ subMeshCount: 0
+ m_StaticBatchRoot: {fileID: 0}
+ m_ProbeAnchor: {fileID: 0}
+ m_LightProbeVolumeOverride: {fileID: 0}
+ m_ScaleInLightmap: 1
+ m_ReceiveGI: 1
+ m_PreserveUVs: 0
+ m_IgnoreNormalsForChartDetection: 0
+ m_ImportantGI: 0
+ m_StitchLightmapSeams: 1
+ m_SelectedEditorRenderState: 3
+ m_MinimumChartSize: 4
+ m_AutoUVMaxDistance: 0.5
+ m_AutoUVMaxAngle: 89
+ m_LightmapParameters: {fileID: 0}
+ m_SortingLayerID: 0
+ m_SortingLayer: 0
+ m_SortingOrder: 0
+ m_AdditionalVertexStreams: {fileID: 0}
+--- !u!33 &117850985
+MeshFilter:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 117850981}
+ m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0}
+--- !u!114 &117850986
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 117850981}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: f4798ff58957f62449d109e13a21fbba, type: 3}
+ m_Name:
+ m_EditorClassIdentifier:
+--- !u!1 &520135022
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 520135024}
+ - component: {fileID: 520135023}
+ - component: {fileID: 520135025}
+ m_Layer: 0
+ m_Name: Directional Light
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!108 &520135023
+Light:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 520135022}
+ m_Enabled: 1
+ serializedVersion: 10
+ m_Type: 1
+ m_Shape: 0
+ m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1}
+ m_Intensity: 1
+ m_Range: 10
+ m_SpotAngle: 30
+ m_InnerSpotAngle: 21.80208
+ m_CookieSize: 10
+ m_Shadows:
+ m_Type: 2
+ m_Resolution: -1
+ m_CustomResolution: -1
+ m_Strength: 1
+ m_Bias: 0.05
+ m_NormalBias: 0.4
+ m_NearPlane: 0.2
+ m_CullingMatrixOverride:
+ e00: 1
+ e01: 0
+ e02: 0
+ e03: 0
+ e10: 0
+ e11: 1
+ e12: 0
+ e13: 0
+ e20: 0
+ e21: 0
+ e22: 1
+ e23: 0
+ e30: 0
+ e31: 0
+ e32: 0
+ e33: 1
+ m_UseCullingMatrixOverride: 0
+ m_Cookie: {fileID: 0}
+ m_DrawHalo: 0
+ m_Flare: {fileID: 0}
+ m_RenderMode: 0
+ m_CullingMask:
+ serializedVersion: 2
+ m_Bits: 4294967295
+ m_RenderingLayerMask: 1
+ m_Lightmapping: 4
+ m_LightShadowCasterMode: 0
+ m_AreaSize: {x: 1, y: 1}
+ m_BounceIntensity: 1
+ m_ColorTemperature: 6570
+ m_UseColorTemperature: 0
+ m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0}
+ m_UseBoundingSphereOverride: 0
+ m_UseViewFrustumForShadowCasterCull: 1
+ m_ShadowRadius: 0
+ m_ShadowAngle: 0
+--- !u!4 &520135024
+Transform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 520135022}
+ m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261}
+ m_LocalPosition: {x: 0, y: 3, z: 0}
+ m_LocalScale: {x: 1, y: 1, z: 1}
+ m_ConstrainProportionsScale: 0
+ m_Children: []
+ m_Father: {fileID: 0}
+ m_RootOrder: 0
+ m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0}
+--- !u!114 &520135025
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 520135022}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: 474bcb49853aa07438625e644c072ee6, type: 3}
+ m_Name:
+ m_EditorClassIdentifier:
+ m_Version: 3
+ m_UsePipelineSettings: 1
+ m_AdditionalLightsShadowResolutionTier: 2
+ m_LightLayerMask: 1
+ m_RenderingLayers: 1
+ m_CustomShadowLayers: 0
+ m_ShadowLayerMask: 1
+ m_ShadowRenderingLayers: 1
+ m_LightCookieSize: {x: 1, y: 1}
+ m_LightCookieOffset: {x: 0, y: 0}
+ m_SoftShadowQuality: 0
+--- !u!1 &623101536 stripped
+GameObject:
+ m_CorrespondingSourceObject: {fileID: 4231759119073248400, guid: e96cffa9d00b6b545adfeb26165952cc,
+ type: 3}
+ m_PrefabInstance: {fileID: 1894754018}
+ m_PrefabAsset: {fileID: 0}
+--- !u!114 &623101541
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 623101536}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: c494d07a7bc3166488d4f75fed12a580, type: 3}
+ m_Name:
+ m_EditorClassIdentifier:
+ MoveSpeed: 10
+ ViewScrollSpeed: 0.1
+ GameScrollSpeed: 1
+ DragSpeed: 0.5
+ AutoRotateSpeed: 30
+ DistanceToPivot: 30
+ RotationQuantDegrees: 45
+--- !u!1 &1086287179
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 1086287180}
+ m_Layer: 0
+ m_Name: Environment Objects
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!4 &1086287180
+Transform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1086287179}
+ m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+ m_LocalPosition: {x: 0, y: 0, z: 0}
+ m_LocalScale: {x: 1.5, y: 1.5, z: 1.5}
+ m_ConstrainProportionsScale: 0
+ m_Children:
+ - {fileID: 117850982}
+ - {fileID: 1735178365}
+ - {fileID: 1543652227}
+ - {fileID: 1282468167}
+ - {fileID: 1973597450}
+ - {fileID: 9044793}
+ m_Father: {fileID: 0}
+ m_RootOrder: 2
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!1 &1282468166
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 1282468167}
+ - component: {fileID: 1282468170}
+ - component: {fileID: 1282468169}
+ - component: {fileID: 1282468168}
+ - component: {fileID: 1282468171}
+ m_Layer: 0
+ m_Name: Cube (3)
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!4 &1282468167
+Transform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1282468166}
+ m_LocalRotation: {x: 0, y: 0.38268343, z: 0, w: 0.92387956}
+ m_LocalPosition: {x: 1.92, y: 0.33, z: 0.82}
+ m_LocalScale: {x: 1, y: 1, z: 1}
+ m_ConstrainProportionsScale: 0
+ m_Children: []
+ m_Father: {fileID: 1086287180}
+ m_RootOrder: -1
+ m_LocalEulerAnglesHint: {x: 0, y: 45, z: 0}
+--- !u!65 &1282468168
+BoxCollider:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1282468166}
+ m_Material: {fileID: 0}
+ m_IncludeLayers:
+ serializedVersion: 2
+ m_Bits: 0
+ m_ExcludeLayers:
+ serializedVersion: 2
+ m_Bits: 0
+ m_LayerOverridePriority: 0
+ m_IsTrigger: 0
+ m_ProvidesContacts: 0
+ m_Enabled: 1
+ serializedVersion: 3
+ m_Size: {x: 1, y: 1, z: 1}
+ m_Center: {x: 0, y: 0, z: 0}
+--- !u!23 &1282468169
+MeshRenderer:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1282468166}
+ m_Enabled: 1
+ m_CastShadows: 1
+ m_ReceiveShadows: 1
+ m_DynamicOccludee: 1
+ m_StaticShadowCaster: 0
+ m_MotionVectors: 1
+ m_LightProbeUsage: 1
+ m_ReflectionProbeUsage: 1
+ m_RayTracingMode: 2
+ m_RayTraceProcedural: 0
+ m_RenderingLayerMask: 1
+ m_RendererPriority: 0
+ m_Materials:
+ - {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, type: 2}
+ m_StaticBatchInfo:
+ firstSubMesh: 0
+ subMeshCount: 0
+ m_StaticBatchRoot: {fileID: 0}
+ m_ProbeAnchor: {fileID: 0}
+ m_LightProbeVolumeOverride: {fileID: 0}
+ m_ScaleInLightmap: 1
+ m_ReceiveGI: 1
+ m_PreserveUVs: 0
+ m_IgnoreNormalsForChartDetection: 0
+ m_ImportantGI: 0
+ m_StitchLightmapSeams: 1
+ m_SelectedEditorRenderState: 3
+ m_MinimumChartSize: 4
+ m_AutoUVMaxDistance: 0.5
+ m_AutoUVMaxAngle: 89
+ m_LightmapParameters: {fileID: 0}
+ m_SortingLayerID: 0
+ m_SortingLayer: 0
+ m_SortingOrder: 0
+ m_AdditionalVertexStreams: {fileID: 0}
+--- !u!33 &1282468170
+MeshFilter:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1282468166}
+ m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0}
+--- !u!114 &1282468171
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1282468166}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: f4798ff58957f62449d109e13a21fbba, type: 3}
+ m_Name:
+ m_EditorClassIdentifier:
+--- !u!1 &1543652226
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 1543652227}
+ - component: {fileID: 1543652230}
+ - component: {fileID: 1543652229}
+ - component: {fileID: 1543652228}
+ - component: {fileID: 1543652231}
+ m_Layer: 0
+ m_Name: Cube (2)
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!4 &1543652227
+Transform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1543652226}
+ m_LocalRotation: {x: 0, y: 0.38268343, z: 0, w: 0.92387956}
+ m_LocalPosition: {x: 3.65, y: 1.96, z: 1.79}
+ m_LocalScale: {x: 1, y: 1, z: 1}
+ m_ConstrainProportionsScale: 0
+ m_Children: []
+ m_Father: {fileID: 1086287180}
+ m_RootOrder: -1
+ m_LocalEulerAnglesHint: {x: 0, y: 45, z: 0}
+--- !u!65 &1543652228
+BoxCollider:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1543652226}
+ m_Material: {fileID: 0}
+ m_IncludeLayers:
+ serializedVersion: 2
+ m_Bits: 0
+ m_ExcludeLayers:
+ serializedVersion: 2
+ m_Bits: 0
+ m_LayerOverridePriority: 0
+ m_IsTrigger: 0
+ m_ProvidesContacts: 0
+ m_Enabled: 1
+ serializedVersion: 3
+ m_Size: {x: 1, y: 1, z: 1}
+ m_Center: {x: 0, y: 0, z: 0}
+--- !u!23 &1543652229
+MeshRenderer:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1543652226}
+ m_Enabled: 1
+ m_CastShadows: 1
+ m_ReceiveShadows: 1
+ m_DynamicOccludee: 1
+ m_StaticShadowCaster: 0
+ m_MotionVectors: 1
+ m_LightProbeUsage: 1
+ m_ReflectionProbeUsage: 1
+ m_RayTracingMode: 2
+ m_RayTraceProcedural: 0
+ m_RenderingLayerMask: 1
+ m_RendererPriority: 0
+ m_Materials:
+ - {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, type: 2}
+ m_StaticBatchInfo:
+ firstSubMesh: 0
+ subMeshCount: 0
+ m_StaticBatchRoot: {fileID: 0}
+ m_ProbeAnchor: {fileID: 0}
+ m_LightProbeVolumeOverride: {fileID: 0}
+ m_ScaleInLightmap: 1
+ m_ReceiveGI: 1
+ m_PreserveUVs: 0
+ m_IgnoreNormalsForChartDetection: 0
+ m_ImportantGI: 0
+ m_StitchLightmapSeams: 1
+ m_SelectedEditorRenderState: 3
+ m_MinimumChartSize: 4
+ m_AutoUVMaxDistance: 0.5
+ m_AutoUVMaxAngle: 89
+ m_LightmapParameters: {fileID: 0}
+ m_SortingLayerID: 0
+ m_SortingLayer: 0
+ m_SortingOrder: 0
+ m_AdditionalVertexStreams: {fileID: 0}
+--- !u!33 &1543652230
+MeshFilter:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1543652226}
+ m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0}
+--- !u!114 &1543652231
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1543652226}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: f4798ff58957f62449d109e13a21fbba, type: 3}
+ m_Name:
+ m_EditorClassIdentifier:
+--- !u!1 &1735178364
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 1735178365}
+ - component: {fileID: 1735178368}
+ - component: {fileID: 1735178367}
+ - component: {fileID: 1735178366}
+ - component: {fileID: 1735178369}
+ m_Layer: 0
+ m_Name: Cylinder
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!4 &1735178365
+Transform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1735178364}
+ m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+ m_LocalPosition: {x: 0, y: -0.5, z: 3.64}
+ m_LocalScale: {x: 2, y: 2, z: 2}
+ m_ConstrainProportionsScale: 0
+ m_Children: []
+ m_Father: {fileID: 1086287180}
+ m_RootOrder: -1
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!136 &1735178366
+CapsuleCollider:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1735178364}
+ m_Material: {fileID: 0}
+ m_IncludeLayers:
+ serializedVersion: 2
+ m_Bits: 0
+ m_ExcludeLayers:
+ serializedVersion: 2
+ m_Bits: 0
+ m_LayerOverridePriority: 0
+ m_IsTrigger: 0
+ m_ProvidesContacts: 0
+ m_Enabled: 1
+ serializedVersion: 2
+ m_Radius: 0.5000001
+ m_Height: 2
+ m_Direction: 1
+ m_Center: {x: 0.000000059604645, y: 0, z: -0.00000008940697}
+--- !u!23 &1735178367
+MeshRenderer:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1735178364}
+ m_Enabled: 1
+ m_CastShadows: 1
+ m_ReceiveShadows: 1
+ m_DynamicOccludee: 1
+ m_StaticShadowCaster: 0
+ m_MotionVectors: 1
+ m_LightProbeUsage: 1
+ m_ReflectionProbeUsage: 1
+ m_RayTracingMode: 2
+ m_RayTraceProcedural: 0
+ m_RenderingLayerMask: 1
+ m_RendererPriority: 0
+ m_Materials:
+ - {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, type: 2}
+ m_StaticBatchInfo:
+ firstSubMesh: 0
+ subMeshCount: 0
+ m_StaticBatchRoot: {fileID: 0}
+ m_ProbeAnchor: {fileID: 0}
+ m_LightProbeVolumeOverride: {fileID: 0}
+ m_ScaleInLightmap: 1
+ m_ReceiveGI: 1
+ m_PreserveUVs: 0
+ m_IgnoreNormalsForChartDetection: 0
+ m_ImportantGI: 0
+ m_StitchLightmapSeams: 1
+ m_SelectedEditorRenderState: 3
+ m_MinimumChartSize: 4
+ m_AutoUVMaxDistance: 0.5
+ m_AutoUVMaxAngle: 89
+ m_LightmapParameters: {fileID: 0}
+ m_SortingLayerID: 0
+ m_SortingLayer: 0
+ m_SortingOrder: 0
+ m_AdditionalVertexStreams: {fileID: 0}
+--- !u!33 &1735178368
+MeshFilter:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1735178364}
+ m_Mesh: {fileID: 10206, guid: 0000000000000000e000000000000000, type: 0}
+--- !u!114 &1735178369
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1735178364}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: f4798ff58957f62449d109e13a21fbba, type: 3}
+ m_Name:
+ m_EditorClassIdentifier:
+--- !u!1 &1748296576 stripped
+GameObject:
+ m_CorrespondingSourceObject: {fileID: 6842119547268722464, guid: e96cffa9d00b6b545adfeb26165952cc,
+ type: 3}
+ m_PrefabInstance: {fileID: 1894754018}
+ m_PrefabAsset: {fileID: 0}
+--- !u!20 &1748296581 stripped
+Camera:
+ m_CorrespondingSourceObject: {fileID: 1798342755243477739, guid: e96cffa9d00b6b545adfeb26165952cc,
+ type: 3}
+ m_PrefabInstance: {fileID: 1894754018}
+ m_PrefabAsset: {fileID: 0}
+--- !u!114 &1748296582
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1748296576}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: 61da2c9a624d7e440994f25060697d82, type: 3}
+ m_Name:
+ m_EditorClassIdentifier:
+ ViewCamera: {fileID: 1748296581}
+--- !u!1001 &1894754018
+PrefabInstance:
+ m_ObjectHideFlags: 0
+ serializedVersion: 2
+ m_Modification:
+ serializedVersion: 3
+ m_TransformParent: {fileID: 0}
+ m_Modifications:
+ - target: {fileID: 1798342755243477739, guid: e96cffa9d00b6b545adfeb26165952cc,
+ type: 3}
+ propertyPath: orthographic size
+ value: 4.9722223
+ objectReference: {fileID: 0}
+ - target: {fileID: 1813454538314249935, guid: e96cffa9d00b6b545adfeb26165952cc,
+ type: 3}
+ propertyPath: m_LocalScale.x
+ value: 17.777779
+ objectReference: {fileID: 0}
+ - target: {fileID: 1813454538314249935, guid: e96cffa9d00b6b545adfeb26165952cc,
+ type: 3}
+ propertyPath: m_LocalScale.y
+ value: 10
+ objectReference: {fileID: 0}
+ - target: {fileID: 2255326839739188927, guid: e96cffa9d00b6b545adfeb26165952cc,
+ type: 3}
+ propertyPath: m_Name
+ value: PixelCameraSystem
+ objectReference: {fileID: 0}
+ - target: {fileID: 2475294716756555193, guid: e96cffa9d00b6b545adfeb26165952cc,
+ type: 3}
+ propertyPath: m_LocalPosition.x
+ value: 0.01019054
+ objectReference: {fileID: 0}
+ - target: {fileID: 2475294716756555193, guid: e96cffa9d00b6b545adfeb26165952cc,
+ type: 3}
+ propertyPath: m_LocalPosition.y
+ value: 0.0007158518
+ objectReference: {fileID: 0}
+ - target: {fileID: 3132409262940554809, guid: e96cffa9d00b6b545adfeb26165952cc,
+ type: 3}
+ propertyPath: m_RootOrder
+ value: 1
+ objectReference: {fileID: 0}
+ - target: {fileID: 3132409262940554809, guid: e96cffa9d00b6b545adfeb26165952cc,
+ type: 3}
+ propertyPath: m_LocalPosition.x
+ value: -1.3786983
+ objectReference: {fileID: 0}
+ - target: {fileID: 3132409262940554809, guid: e96cffa9d00b6b545adfeb26165952cc,
+ type: 3}
+ propertyPath: m_LocalPosition.y
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 3132409262940554809, guid: e96cffa9d00b6b545adfeb26165952cc,
+ type: 3}
+ propertyPath: m_LocalPosition.z
+ value: -20.377922
+ objectReference: {fileID: 0}
+ - target: {fileID: 3132409262940554809, guid: e96cffa9d00b6b545adfeb26165952cc,
+ type: 3}
+ propertyPath: m_LocalRotation.w
+ value: 1
+ objectReference: {fileID: 0}
+ - target: {fileID: 3132409262940554809, guid: e96cffa9d00b6b545adfeb26165952cc,
+ type: 3}
+ propertyPath: m_LocalRotation.x
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 3132409262940554809, guid: e96cffa9d00b6b545adfeb26165952cc,
+ type: 3}
+ propertyPath: m_LocalRotation.y
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 3132409262940554809, guid: e96cffa9d00b6b545adfeb26165952cc,
+ type: 3}
+ propertyPath: m_LocalRotation.z
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 3132409262940554809, guid: e96cffa9d00b6b545adfeb26165952cc,
+ type: 3}
+ propertyPath: m_LocalEulerAnglesHint.x
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 3132409262940554809, guid: e96cffa9d00b6b545adfeb26165952cc,
+ type: 3}
+ propertyPath: m_LocalEulerAnglesHint.y
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 3132409262940554809, guid: e96cffa9d00b6b545adfeb26165952cc,
+ type: 3}
+ propertyPath: m_LocalEulerAnglesHint.z
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 7303396614074331432, guid: e96cffa9d00b6b545adfeb26165952cc,
+ type: 3}
+ propertyPath: m_LocalPosition.y
+ value: 13.84
+ objectReference: {fileID: 0}
+ - target: {fileID: 7303396614074331432, guid: e96cffa9d00b6b545adfeb26165952cc,
+ type: 3}
+ propertyPath: m_LocalPosition.z
+ value: -0.87
+ objectReference: {fileID: 0}
+ - target: {fileID: 7303396614074331432, guid: e96cffa9d00b6b545adfeb26165952cc,
+ type: 3}
+ propertyPath: m_LocalRotation.w
+ value: 0.9659258
+ objectReference: {fileID: 0}
+ - target: {fileID: 7303396614074331432, guid: e96cffa9d00b6b545adfeb26165952cc,
+ type: 3}
+ propertyPath: m_LocalRotation.x
+ value: 0.2588191
+ objectReference: {fileID: 0}
+ - target: {fileID: 7303396614074331432, guid: e96cffa9d00b6b545adfeb26165952cc,
+ type: 3}
+ propertyPath: m_LocalEulerAnglesHint.x
+ value: 30
+ objectReference: {fileID: 0}
+ - target: {fileID: 8788124287499514057, guid: e96cffa9d00b6b545adfeb26165952cc,
+ type: 3}
+ propertyPath: m_LocalPosition.x
+ value: -0.010190606
+ objectReference: {fileID: 0}
+ - target: {fileID: 8788124287499514057, guid: e96cffa9d00b6b545adfeb26165952cc,
+ type: 3}
+ propertyPath: m_LocalPosition.y
+ value: 13.845427
+ objectReference: {fileID: 0}
+ - target: {fileID: 8788124287499514057, guid: e96cffa9d00b6b545adfeb26165952cc,
+ type: 3}
+ propertyPath: m_LocalPosition.z
+ value: -0.88083076
+ objectReference: {fileID: 0}
+ - target: {fileID: 8788124287499514057, guid: e96cffa9d00b6b545adfeb26165952cc,
+ type: 3}
+ propertyPath: m_LocalRotation.w
+ value: 0.9659258
+ objectReference: {fileID: 0}
+ - target: {fileID: 8788124287499514057, guid: e96cffa9d00b6b545adfeb26165952cc,
+ type: 3}
+ propertyPath: m_LocalRotation.x
+ value: 0.2588191
+ objectReference: {fileID: 0}
+ - target: {fileID: 9205371885998440386, guid: e96cffa9d00b6b545adfeb26165952cc,
+ type: 3}
+ propertyPath: m_TargetTexture
+ value:
+ objectReference: {fileID: 1985181849}
+ m_RemovedComponents: []
+ m_RemovedGameObjects: []
+ m_AddedGameObjects: []
+ m_AddedComponents:
+ - targetCorrespondingSourceObject: {fileID: 4231759119073248400, guid: e96cffa9d00b6b545adfeb26165952cc,
+ type: 3}
+ insertIndex: -1
+ addedObject: {fileID: 623101541}
+ - targetCorrespondingSourceObject: {fileID: 6842119547268722464, guid: e96cffa9d00b6b545adfeb26165952cc,
+ type: 3}
+ insertIndex: -1
+ addedObject: {fileID: 1748296582}
+ m_SourcePrefab: {fileID: 100100000, guid: e96cffa9d00b6b545adfeb26165952cc, type: 3}
+--- !u!1 &1973597449
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 1973597450}
+ - component: {fileID: 1973597453}
+ - component: {fileID: 1973597452}
+ - component: {fileID: 1973597451}
+ - component: {fileID: 1973597454}
+ m_Layer: 0
+ m_Name: Sphere
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!4 &1973597450
+Transform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1973597449}
+ m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+ m_LocalPosition: {x: -5.94, y: 0.85, z: -1.74}
+ m_LocalScale: {x: 1, y: 1, z: 1}
+ m_ConstrainProportionsScale: 0
+ m_Children: []
+ m_Father: {fileID: 1086287180}
+ m_RootOrder: -1
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!135 &1973597451
+SphereCollider:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1973597449}
+ m_Material: {fileID: 0}
+ m_IncludeLayers:
+ serializedVersion: 2
+ m_Bits: 0
+ m_ExcludeLayers:
+ serializedVersion: 2
+ m_Bits: 0
+ m_LayerOverridePriority: 0
+ m_IsTrigger: 0
+ m_ProvidesContacts: 0
+ m_Enabled: 1
+ serializedVersion: 3
+ m_Radius: 0.5
+ m_Center: {x: 0, y: 0, z: 0}
+--- !u!23 &1973597452
+MeshRenderer:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1973597449}
+ m_Enabled: 1
+ m_CastShadows: 1
+ m_ReceiveShadows: 1
+ m_DynamicOccludee: 1
+ m_StaticShadowCaster: 0
+ m_MotionVectors: 1
+ m_LightProbeUsage: 1
+ m_ReflectionProbeUsage: 1
+ m_RayTracingMode: 2
+ m_RayTraceProcedural: 0
+ m_RenderingLayerMask: 1
+ m_RendererPriority: 0
+ m_Materials:
+ - {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, type: 2}
+ m_StaticBatchInfo:
+ firstSubMesh: 0
+ subMeshCount: 0
+ m_StaticBatchRoot: {fileID: 0}
+ m_ProbeAnchor: {fileID: 0}
+ m_LightProbeVolumeOverride: {fileID: 0}
+ m_ScaleInLightmap: 1
+ m_ReceiveGI: 1
+ m_PreserveUVs: 0
+ m_IgnoreNormalsForChartDetection: 0
+ m_ImportantGI: 0
+ m_StitchLightmapSeams: 1
+ m_SelectedEditorRenderState: 3
+ m_MinimumChartSize: 4
+ m_AutoUVMaxDistance: 0.5
+ m_AutoUVMaxAngle: 89
+ m_LightmapParameters: {fileID: 0}
+ m_SortingLayerID: 0
+ m_SortingLayer: 0
+ m_SortingOrder: 0
+ m_AdditionalVertexStreams: {fileID: 0}
+--- !u!33 &1973597453
+MeshFilter:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1973597449}
+ m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0}
+--- !u!114 &1973597454
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1973597449}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: f4798ff58957f62449d109e13a21fbba, type: 3}
+ m_Name:
+ m_EditorClassIdentifier:
+--- !u!84 &1985181849
+RenderTexture:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_Name:
+ m_ImageContentsHash:
+ serializedVersion: 2
+ Hash: 00000000000000000000000000000000
+ m_ForcedFallbackFormat: 4
+ m_DownscaleFallback: 0
+ m_IsAlphaChannelOptional: 0
+ serializedVersion: 5
+ m_Width: 640
+ m_Height: 360
+ m_AntiAliasing: 1
+ m_MipCount: -1
+ m_DepthStencilFormat: 94
+ m_ColorFormat: 4
+ m_MipMap: 0
+ m_GenerateMips: 1
+ m_SRGB: 1
+ m_UseDynamicScale: 0
+ m_BindMS: 0
+ m_EnableCompatibleFormat: 1
+ m_TextureSettings:
+ serializedVersion: 2
+ m_FilterMode: 0
+ m_Aniso: 1
+ m_MipBias: 0
+ m_WrapU: 1
+ m_WrapV: 1
+ m_WrapW: 1
+ m_Dimension: 2
+ m_VolumeDepth: 1
+ m_ShadowSamplingMode: 2
diff --git a/Assets/3DPixelCamera/URP/DemoScene.unity.meta b/Assets/3DPixelCamera/URP/DemoScene.unity.meta
new file mode 100644
index 000000000..710fa0308
--- /dev/null
+++ b/Assets/3DPixelCamera/URP/DemoScene.unity.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 67fa8744e3c0f97478b2a6fd3292b65d
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/3DPixelCamera/URP/PixelCameraSystem.prefab b/Assets/3DPixelCamera/URP/PixelCameraSystem.prefab
new file mode 100644
index 000000000..65c813bb1
--- /dev/null
+++ b/Assets/3DPixelCamera/URP/PixelCameraSystem.prefab
@@ -0,0 +1,496 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!1 &1532677598533230704
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 7303396614074331432}
+ m_Layer: 0
+ m_Name: PixelCameraTransform
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!4 &7303396614074331432
+Transform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1532677598533230704}
+ m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+ m_LocalPosition: {x: 0, y: 0, z: 0}
+ m_LocalScale: {x: 1, y: 1, z: 1}
+ m_ConstrainProportionsScale: 0
+ m_Children: []
+ m_Father: {fileID: 3132409262940554809}
+ m_RootOrder: -1
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!1 &2255326839739188927
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 3132409262940554809}
+ m_Layer: 0
+ m_Name: PixelCameraSystem
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!4 &3132409262940554809
+Transform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 2255326839739188927}
+ m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+ m_LocalPosition: {x: 0, y: 0, z: 0}
+ m_LocalScale: {x: 1, y: 1, z: 1}
+ m_ConstrainProportionsScale: 0
+ m_Children:
+ - {fileID: 7303396614074331432}
+ - {fileID: 8788124287499514057}
+ m_Father: {fileID: 0}
+ m_RootOrder: 0
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!1 &3474214803470865388
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 1813454538314249935}
+ - component: {fileID: 5422343619921320258}
+ - component: {fileID: 418977516687070584}
+ - component: {fileID: 5593218058142784318}
+ m_Layer: 0
+ m_Name: QuadCanvas
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!4 &1813454538314249935
+Transform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 3474214803470865388}
+ m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+ m_LocalPosition: {x: 0, y: 0, z: 0}
+ m_LocalScale: {x: 19.802168, y: 10.055555, z: 1}
+ m_ConstrainProportionsScale: 0
+ m_Children: []
+ m_Father: {fileID: 8987800775158610402}
+ m_RootOrder: -1
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!33 &5422343619921320258
+MeshFilter:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 3474214803470865388}
+ m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0}
+--- !u!23 &418977516687070584
+MeshRenderer:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 3474214803470865388}
+ m_Enabled: 1
+ m_CastShadows: 0
+ m_ReceiveShadows: 1
+ m_DynamicOccludee: 1
+ m_StaticShadowCaster: 0
+ m_MotionVectors: 1
+ m_LightProbeUsage: 0
+ m_ReflectionProbeUsage: 1
+ m_RayTracingMode: 2
+ m_RayTraceProcedural: 0
+ m_RenderingLayerMask: 1
+ m_RendererPriority: 0
+ m_Materials:
+ - {fileID: 2100000, guid: 1af8e993bbdb2f547989713359c47b1c, type: 2}
+ m_StaticBatchInfo:
+ firstSubMesh: 0
+ subMeshCount: 0
+ m_StaticBatchRoot: {fileID: 0}
+ m_ProbeAnchor: {fileID: 0}
+ m_LightProbeVolumeOverride: {fileID: 0}
+ m_ScaleInLightmap: 1
+ m_ReceiveGI: 1
+ m_PreserveUVs: 0
+ m_IgnoreNormalsForChartDetection: 0
+ m_ImportantGI: 0
+ m_StitchLightmapSeams: 1
+ m_SelectedEditorRenderState: 3
+ m_MinimumChartSize: 4
+ m_AutoUVMaxDistance: 0.5
+ m_AutoUVMaxAngle: 89
+ m_LightmapParameters: {fileID: 0}
+ m_SortingLayerID: 0
+ m_SortingLayer: 0
+ m_SortingOrder: 0
+ m_AdditionalVertexStreams: {fileID: 0}
+--- !u!114 &5593218058142784318
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 3474214803470865388}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: ab692ebf91361b44cbd447f7d7b5fddf, type: 3}
+ m_Name:
+ m_EditorClassIdentifier:
+--- !u!1 &4231759119073248400
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 8788124287499514057}
+ - component: {fileID: 9205371885998440386}
+ - component: {fileID: 6298985930916582049}
+ - component: {fileID: 4103191127918928509}
+ m_Layer: 0
+ m_Name: PixelCamera
+ m_TagString: MainCamera
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!4 &8788124287499514057
+Transform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 4231759119073248400}
+ m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
+ m_LocalPosition: {x: 0, y: 0, z: 0}
+ m_LocalScale: {x: 1, y: 1, z: 1}
+ m_ConstrainProportionsScale: 0
+ m_Children:
+ - {fileID: 8987800775158610402}
+ m_Father: {fileID: 3132409262940554809}
+ m_RootOrder: -1
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!20 &9205371885998440386
+Camera:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 4231759119073248400}
+ m_Enabled: 1
+ serializedVersion: 2
+ m_ClearFlags: 2
+ m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0}
+ m_projectionMatrixMode: 1
+ m_GateFitMode: 2
+ m_FOVAxisMode: 0
+ m_Iso: 200
+ m_ShutterSpeed: 0.005
+ m_Aperture: 16
+ m_FocusDistance: 10
+ m_FocalLength: 50
+ m_BladeCount: 5
+ m_Curvature: {x: 2, y: 11}
+ m_BarrelClipping: 0.25
+ m_Anamorphism: 0
+ m_SensorSize: {x: 36, y: 24}
+ m_LensShift: {x: 0, y: 0}
+ m_NormalizedViewPortRect:
+ serializedVersion: 2
+ x: 0
+ y: 0
+ width: 1
+ height: 1
+ near clip plane: 0.3
+ far clip plane: 1000
+ field of view: 60
+ orthographic: 1
+ orthographic size: 5
+ m_Depth: 0
+ m_CullingMask:
+ serializedVersion: 2
+ m_Bits: 4294967295
+ m_RenderingPath: -1
+ m_TargetTexture: {fileID: 0}
+ m_TargetDisplay: 0
+ m_TargetEye: 3
+ m_HDR: 1
+ m_AllowMSAA: 1
+ m_AllowDynamicResolution: 0
+ m_ForceIntoRT: 0
+ m_OcclusionCulling: 1
+ m_StereoConvergence: 10
+ m_StereoSeparation: 0.022
+--- !u!114 &6298985930916582049
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 4231759119073248400}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: a6fe4c3a8238df440bdf10c687b2537f, type: 3}
+ m_Name:
+ m_EditorClassIdentifier:
+ FollowedTransform: {fileID: 7303396614074331432}
+ VoxelGridMovement: 1
+ SubpixelAdjustments: 1
+ FollowRotation: 1
+ resolutionSynchronizationMode: 0
+ GameResolution: {x: 640, y: 360}
+ ControlGameZoom: 1
+ GameCameraZoom: 5
+ ViewCameraZoom: 1
+--- !u!114 &4103191127918928509
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 4231759119073248400}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: a79441f348de89743a2939f4d699eac1, type: 3}
+ m_Name:
+ m_EditorClassIdentifier:
+ m_RenderShadows: 1
+ m_RequiresDepthTextureOption: 2
+ m_RequiresOpaqueTextureOption: 2
+ m_CameraType: 0
+ m_Cameras: []
+ m_RendererIndex: -1
+ m_VolumeLayerMask:
+ serializedVersion: 2
+ m_Bits: 1
+ m_VolumeTrigger: {fileID: 0}
+ m_VolumeFrameworkUpdateModeOption: 2
+ m_RenderPostProcessing: 0
+ m_Antialiasing: 0
+ m_AntialiasingQuality: 2
+ m_StopNaN: 0
+ m_Dithering: 0
+ m_ClearDepth: 1
+ m_AllowXRRendering: 1
+ m_AllowHDROutput: 1
+ m_UseScreenCoordOverride: 0
+ m_ScreenSizeOverride: {x: 0, y: 0, z: 0, w: 0}
+ m_ScreenCoordScaleBias: {x: 0, y: 0, z: 0, w: 0}
+ m_RequiresDepthTexture: 0
+ m_RequiresColorTexture: 0
+ m_Version: 2
+ m_TaaSettings:
+ quality: 3
+ frameInfluence: 0.1
+ jitterScale: 1
+ mipBias: 0
+ varianceClampScale: 0.9
+ contrastAdaptiveSharpening: 0
+--- !u!1 &6842119547268722464
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 2475294716756555193}
+ - component: {fileID: 1798342755243477739}
+ - component: {fileID: 439820793684178854}
+ - component: {fileID: 3231981177195013634}
+ - component: {fileID: 1032179972197267321}
+ m_Layer: 0
+ m_Name: ViewCamera
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!4 &2475294716756555193
+Transform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 6842119547268722464}
+ m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+ m_LocalPosition: {x: 0, y: 0.008579807, z: -1}
+ m_LocalScale: {x: 1, y: 1, z: 1}
+ m_ConstrainProportionsScale: 0
+ m_Children: []
+ m_Father: {fileID: 8987800775158610402}
+ m_RootOrder: -1
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!20 &1798342755243477739
+Camera:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 6842119547268722464}
+ m_Enabled: 1
+ serializedVersion: 2
+ m_ClearFlags: 2
+ m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0}
+ m_projectionMatrixMode: 1
+ m_GateFitMode: 2
+ m_FOVAxisMode: 0
+ m_Iso: 200
+ m_ShutterSpeed: 0.005
+ m_Aperture: 16
+ m_FocusDistance: 10
+ m_FocalLength: 50
+ m_BladeCount: 5
+ m_Curvature: {x: 2, y: 11}
+ m_BarrelClipping: 0.25
+ m_Anamorphism: 0
+ m_SensorSize: {x: 36, y: 24}
+ m_LensShift: {x: 0, y: 0}
+ m_NormalizedViewPortRect:
+ serializedVersion: 2
+ x: 0
+ y: 0
+ width: 1
+ height: 1
+ near clip plane: 0
+ far clip plane: 1001
+ field of view: 60
+ orthographic: 1
+ orthographic size: 5
+ m_Depth: 0
+ m_CullingMask:
+ serializedVersion: 2
+ m_Bits: 4294967295
+ m_RenderingPath: -1
+ m_TargetTexture: {fileID: 0}
+ m_TargetDisplay: 0
+ m_TargetEye: 3
+ m_HDR: 1
+ m_AllowMSAA: 1
+ m_AllowDynamicResolution: 0
+ m_ForceIntoRT: 0
+ m_OcclusionCulling: 1
+ m_StereoConvergence: 10
+ m_StereoSeparation: 0.022
+--- !u!81 &439820793684178854
+AudioListener:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 6842119547268722464}
+ m_Enabled: 1
+--- !u!114 &3231981177195013634
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 6842119547268722464}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: a79441f348de89743a2939f4d699eac1, type: 3}
+ m_Name:
+ m_EditorClassIdentifier:
+ m_RenderShadows: 0
+ m_RequiresDepthTextureOption: 2
+ m_RequiresOpaqueTextureOption: 2
+ m_CameraType: 0
+ m_Cameras: []
+ m_RendererIndex: -1
+ m_VolumeLayerMask:
+ serializedVersion: 2
+ m_Bits: 1
+ m_VolumeTrigger: {fileID: 0}
+ m_VolumeFrameworkUpdateModeOption: 2
+ m_RenderPostProcessing: 0
+ m_Antialiasing: 0
+ m_AntialiasingQuality: 2
+ m_StopNaN: 0
+ m_Dithering: 0
+ m_ClearDepth: 1
+ m_AllowXRRendering: 1
+ m_AllowHDROutput: 1
+ m_UseScreenCoordOverride: 0
+ m_ScreenSizeOverride: {x: 0, y: 0, z: 0, w: 0}
+ m_ScreenCoordScaleBias: {x: 0, y: 0, z: 0, w: 0}
+ m_RequiresDepthTexture: 0
+ m_RequiresColorTexture: 0
+ m_Version: 2
+ m_TaaSettings:
+ quality: 3
+ frameInfluence: 0.1
+ jitterScale: 1
+ mipBias: 0
+ varianceClampScale: 0.9
+ contrastAdaptiveSharpening: 0
+--- !u!114 &1032179972197267321
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 6842119547268722464}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: de5b95231816236418041ca173b33a29, type: 3}
+ m_Name:
+ m_EditorClassIdentifier:
+--- !u!1 &7295925279294691889
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 8987800775158610402}
+ m_Layer: 0
+ m_Name: UpscaledDisplay
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!4 &8987800775158610402
+Transform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 7295925279294691889}
+ m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+ m_LocalPosition: {x: 0, y: 0, z: -1}
+ m_LocalScale: {x: 1, y: 1, z: 1}
+ m_ConstrainProportionsScale: 0
+ m_Children:
+ - {fileID: 2475294716756555193}
+ - {fileID: 1813454538314249935}
+ m_Father: {fileID: 8788124287499514057}
+ m_RootOrder: -1
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
diff --git a/Assets/3DPixelCamera/URP/PixelCameraSystem.prefab.meta b/Assets/3DPixelCamera/URP/PixelCameraSystem.prefab.meta
new file mode 100644
index 000000000..c9dcc70b4
--- /dev/null
+++ b/Assets/3DPixelCamera/URP/PixelCameraSystem.prefab.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: e96cffa9d00b6b545adfeb26165952cc
+PrefabImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/3DPixelCamera/URP/UpscaleMaterialURP.mat b/Assets/3DPixelCamera/URP/UpscaleMaterialURP.mat
new file mode 100644
index 000000000..2b3e0dbc0
--- /dev/null
+++ b/Assets/3DPixelCamera/URP/UpscaleMaterialURP.mat
@@ -0,0 +1,135 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!21 &2100000
+Material:
+ serializedVersion: 8
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_Name: UpscaleMaterialURP
+ m_Shader: {fileID: -6465566751694194690, guid: c63d04c1c20ea83498addf7813ae3dc5,
+ type: 3}
+ m_Parent: {fileID: 0}
+ m_ModifiedSerializedProperties: 0
+ m_ValidKeywords: []
+ m_InvalidKeywords: []
+ m_LightmapFlags: 4
+ m_EnableInstancingVariants: 0
+ m_DoubleSidedGI: 0
+ m_CustomRenderQueue: -1
+ stringTagMap: {}
+ disabledShaderPasses:
+ - MOTIONVECTORS
+ m_LockedProperties:
+ m_SavedProperties:
+ serializedVersion: 3
+ m_TexEnvs:
+ - _BaseMap:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - _BumpMap:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - _DetailAlbedoMap:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - _DetailMask:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - _DetailNormalMap:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - _DownscaledTexture:
+ m_Texture: {fileID: 8400000, guid: b341653440931de4ba25940d113f4375, type: 2}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - _EmissionMap:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - _LowResTexture:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - _MainTex:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - _MetallicGlossMap:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - _OcclusionMap:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - _ParallaxMap:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - unity_Lightmaps:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - unity_LightmapsInd:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - unity_ShadowMasks:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ m_Ints: []
+ m_Floats:
+ - _AlphaClip: 0
+ - _AlphaToMask: 0
+ - _Blend: 0
+ - _BlendOp: 0
+ - _BumpScale: 1
+ - _Cull: 2
+ - _Cutoff: 0.5
+ - _DetailNormalMapScale: 1
+ - _DstBlend: 0
+ - _DstBlendAlpha: 0
+ - _GlossMapScale: 1
+ - _Glossiness: 0.5
+ - _GlossyReflections: 1
+ - _Metallic: 0
+ - _Mode: 0
+ - _OcclusionStrength: 1
+ - _Parallax: 0.02
+ - _QueueControl: 0
+ - _QueueOffset: 0
+ - _SampleGI: 0
+ - _SmoothnessTextureChannel: 0
+ - _SpecularHighlights: 1
+ - _SrcBlend: 1
+ - _SrcBlendAlpha: 1
+ - _Surface: 0
+ - _UVSec: 0
+ - _ZWrite: 1
+ m_Colors:
+ - _BaseColor: {r: 1, g: 1, b: 1, a: 1}
+ - _Color: {r: 1, g: 1, b: 1, a: 1}
+ - _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
+ m_BuildTextureStacks: []
+ m_AllowLocking: 1
+--- !u!114 &4363459520997935123
+MonoBehaviour:
+ m_ObjectHideFlags: 11
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 0}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3}
+ m_Name:
+ m_EditorClassIdentifier:
+ version: 10
diff --git a/Assets/3DPixelCamera/URP/UpscaleMaterialURP.mat.meta b/Assets/3DPixelCamera/URP/UpscaleMaterialURP.mat.meta
new file mode 100644
index 000000000..405bdedee
--- /dev/null
+++ b/Assets/3DPixelCamera/URP/UpscaleMaterialURP.mat.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 1af8e993bbdb2f547989713359c47b1c
+NativeFormatImporter:
+ externalObjects: {}
+ mainObjectFileID: 2100000
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/3DPixelCamera/URP/UpscaleShaderURP.shadergraph b/Assets/3DPixelCamera/URP/UpscaleShaderURP.shadergraph
new file mode 100644
index 000000000..678e9ce23
--- /dev/null
+++ b/Assets/3DPixelCamera/URP/UpscaleShaderURP.shadergraph
@@ -0,0 +1,693 @@
+{
+ "m_SGVersion": 3,
+ "m_Type": "UnityEditor.ShaderGraph.GraphData",
+ "m_ObjectId": "4b4aee54c62b40958070f4140352fba7",
+ "m_Properties": [
+ {
+ "m_Id": "3ba9df8d7b064813844ee1a01ff30884"
+ }
+ ],
+ "m_Keywords": [],
+ "m_Dropdowns": [],
+ "m_CategoryData": [
+ {
+ "m_Id": "5b7e26a64997477b8fceed79720cbe18"
+ }
+ ],
+ "m_Nodes": [
+ {
+ "m_Id": "e89eafddf99b406dba0daa5373d685ee"
+ },
+ {
+ "m_Id": "54acbcd866754623a9971b65c87753b5"
+ },
+ {
+ "m_Id": "3a3ed0c7f46f423bb7e2448b2a885805"
+ },
+ {
+ "m_Id": "b646594906c747a4a535fe5a190c267e"
+ },
+ {
+ "m_Id": "8346d6ed11034b1785db95ef2e8bf371"
+ },
+ {
+ "m_Id": "8d0d097456884c839b0e1bccbd948c83"
+ }
+ ],
+ "m_GroupDatas": [],
+ "m_StickyNoteDatas": [
+ {
+ "m_Id": "2bcf8277985449668ed3ecc75283b25f"
+ }
+ ],
+ "m_Edges": [
+ {
+ "m_OutputSlot": {
+ "m_Node": {
+ "m_Id": "8346d6ed11034b1785db95ef2e8bf371"
+ },
+ "m_SlotId": 0
+ },
+ "m_InputSlot": {
+ "m_Node": {
+ "m_Id": "8d0d097456884c839b0e1bccbd948c83"
+ },
+ "m_SlotId": 1
+ }
+ },
+ {
+ "m_OutputSlot": {
+ "m_Node": {
+ "m_Id": "8d0d097456884c839b0e1bccbd948c83"
+ },
+ "m_SlotId": 0
+ },
+ "m_InputSlot": {
+ "m_Node": {
+ "m_Id": "b646594906c747a4a535fe5a190c267e"
+ },
+ "m_SlotId": 0
+ }
+ }
+ ],
+ "m_VertexContext": {
+ "m_Position": {
+ "x": 878.666748046875,
+ "y": -616.0001220703125
+ },
+ "m_Blocks": [
+ {
+ "m_Id": "e89eafddf99b406dba0daa5373d685ee"
+ },
+ {
+ "m_Id": "54acbcd866754623a9971b65c87753b5"
+ },
+ {
+ "m_Id": "3a3ed0c7f46f423bb7e2448b2a885805"
+ }
+ ]
+ },
+ "m_FragmentContext": {
+ "m_Position": {
+ "x": 879.3333740234375,
+ "y": -363.3334655761719
+ },
+ "m_Blocks": [
+ {
+ "m_Id": "b646594906c747a4a535fe5a190c267e"
+ }
+ ]
+ },
+ "m_PreviewData": {
+ "serializedMesh": {
+ "m_SerializedMesh": "{\"mesh\":{\"instanceID\":0}}",
+ "m_Guid": ""
+ },
+ "preventRotation": false
+ },
+ "m_Path": "Shader Graphs",
+ "m_GraphPrecision": 0,
+ "m_PreviewMode": 2,
+ "m_OutputNode": {
+ "m_Id": ""
+ },
+ "m_ActiveTargets": [
+ {
+ "m_Id": "0d38844c2de34d5ba592090e3a320f9d"
+ }
+ ]
+}
+
+{
+ "m_SGVersion": 0,
+ "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot",
+ "m_ObjectId": "012c063cd77b4055a5d02d510505e55e",
+ "m_Id": 5,
+ "m_DisplayName": "G",
+ "m_SlotType": 1,
+ "m_Hidden": false,
+ "m_ShaderOutputName": "G",
+ "m_StageCapability": 2,
+ "m_Value": 0.0,
+ "m_DefaultValue": 0.0,
+ "m_Labels": []
+}
+
+{
+ "m_SGVersion": 1,
+ "m_Type": "UnityEditor.Rendering.Universal.ShaderGraph.UniversalTarget",
+ "m_ObjectId": "0d38844c2de34d5ba592090e3a320f9d",
+ "m_Datas": [],
+ "m_ActiveSubTarget": {
+ "m_Id": "82a2f491e31c4a83a8bfa01a377c3b68"
+ },
+ "m_AllowMaterialOverride": false,
+ "m_SurfaceType": 0,
+ "m_ZTestMode": 4,
+ "m_ZWriteControl": 0,
+ "m_AlphaMode": 0,
+ "m_RenderFace": 2,
+ "m_AlphaClip": false,
+ "m_CastShadows": true,
+ "m_ReceiveShadows": true,
+ "m_SupportsLODCrossFade": false,
+ "m_CustomEditorGUI": "",
+ "m_SupportVFX": false
+}
+
+{
+ "m_SGVersion": 0,
+ "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot",
+ "m_ObjectId": "1bd6c17f30d843c5bded4563c487ef31",
+ "m_Id": 6,
+ "m_DisplayName": "B",
+ "m_SlotType": 1,
+ "m_Hidden": false,
+ "m_ShaderOutputName": "B",
+ "m_StageCapability": 2,
+ "m_Value": 0.0,
+ "m_DefaultValue": 0.0,
+ "m_Labels": []
+}
+
+{
+ "m_SGVersion": 0,
+ "m_Type": "UnityEditor.ShaderGraph.StickyNoteData",
+ "m_ObjectId": "2bcf8277985449668ed3ecc75283b25f",
+ "m_Title": "Hello!",
+ "m_Content": "This shader is intended to display the game on a quad. The 'LowResTexture' is a low-resolution rendertexture of the game. A full-resolution camera then looks at said quad and performs adjustments to create subpixel movement.\n\nThis way you can have your FX, post-processing, gameobjects, and virtually everything rendered on low-resolution which creates significant boost in performance for GPU. \n\n*** Add \"post-post-processing\" here *** \n\nBecause this shader displays the final result of your game, you can adjust this shader to create your own effects on top of all that.",
+ "m_TextSize": 0,
+ "m_Theme": 0,
+ "m_Position": {
+ "serializedVersion": "2",
+ "x": 360.6666564941406,
+ "y": -648.0,
+ "width": 366.66668701171877,
+ "height": 226.00003051757813
+ },
+ "m_Group": {
+ "m_Id": ""
+ }
+}
+
+{
+ "m_SGVersion": 0,
+ "m_Type": "UnityEditor.ShaderGraph.BlockNode",
+ "m_ObjectId": "3a3ed0c7f46f423bb7e2448b2a885805",
+ "m_Group": {
+ "m_Id": ""
+ },
+ "m_Name": "VertexDescription.Tangent",
+ "m_DrawState": {
+ "m_Expanded": true,
+ "m_Position": {
+ "serializedVersion": "2",
+ "x": 0.0,
+ "y": 0.0,
+ "width": 0.0,
+ "height": 0.0
+ }
+ },
+ "m_Slots": [
+ {
+ "m_Id": "95d25e4d952f48c38ba5e62dc3fab9cd"
+ }
+ ],
+ "synonyms": [],
+ "m_Precision": 0,
+ "m_PreviewExpanded": true,
+ "m_DismissedVersion": 0,
+ "m_PreviewMode": 0,
+ "m_CustomColors": {
+ "m_SerializableColors": []
+ },
+ "m_SerializedDescriptor": "VertexDescription.Tangent"
+}
+
+{
+ "m_SGVersion": 0,
+ "m_Type": "UnityEditor.ShaderGraph.Internal.Texture2DShaderProperty",
+ "m_ObjectId": "3ba9df8d7b064813844ee1a01ff30884",
+ "m_Guid": {
+ "m_GuidSerialized": "cdef0278-d3f3-407a-9b37-d7731b76ad2c"
+ },
+ "m_Name": "LowResTexture",
+ "m_DefaultRefNameVersion": 0,
+ "m_RefNameGeneratedByDisplayName": "",
+ "m_DefaultReferenceName": "Texture2D_3ba9df8d7b064813844ee1a01ff30884",
+ "m_OverrideReferenceName": "_LowResTexture",
+ "m_GeneratePropertyBlock": true,
+ "m_UseCustomSlotLabel": false,
+ "m_CustomSlotLabel": "",
+ "m_DismissedVersion": 0,
+ "m_Precision": 0,
+ "overrideHLSLDeclaration": false,
+ "hlslDeclarationOverride": 0,
+ "m_Hidden": false,
+ "m_Value": {
+ "m_SerializedTexture": "{\"texture\":{\"fileID\":8400000,\"guid\":\"dc06a050ca5352e469850f311104ce88\",\"type\":2}}",
+ "m_Guid": ""
+ },
+ "isMainTexture": false,
+ "useTilingAndOffset": false,
+ "m_Modifiable": true,
+ "m_DefaultType": 0
+}
+
+{
+ "m_SGVersion": 0,
+ "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot",
+ "m_ObjectId": "3e6a598eb5204f6287316d0d3809b215",
+ "m_Id": 7,
+ "m_DisplayName": "A",
+ "m_SlotType": 1,
+ "m_Hidden": false,
+ "m_ShaderOutputName": "A",
+ "m_StageCapability": 2,
+ "m_Value": 0.0,
+ "m_DefaultValue": 0.0,
+ "m_Labels": []
+}
+
+{
+ "m_SGVersion": 0,
+ "m_Type": "UnityEditor.ShaderGraph.PositionMaterialSlot",
+ "m_ObjectId": "4da2c55cfe2e4cf9a6659081084573f0",
+ "m_Id": 0,
+ "m_DisplayName": "Position",
+ "m_SlotType": 0,
+ "m_Hidden": false,
+ "m_ShaderOutputName": "Position",
+ "m_StageCapability": 1,
+ "m_Value": {
+ "x": 0.0,
+ "y": 0.0,
+ "z": 0.0
+ },
+ "m_DefaultValue": {
+ "x": 0.0,
+ "y": 0.0,
+ "z": 0.0
+ },
+ "m_Labels": [],
+ "m_Space": 0
+}
+
+{
+ "m_SGVersion": 0,
+ "m_Type": "UnityEditor.ShaderGraph.SamplerStateMaterialSlot",
+ "m_ObjectId": "5186d854ec8f4e55a948afefab209f95",
+ "m_Id": 3,
+ "m_DisplayName": "Sampler",
+ "m_SlotType": 0,
+ "m_Hidden": false,
+ "m_ShaderOutputName": "Sampler",
+ "m_StageCapability": 3,
+ "m_BareResource": false
+}
+
+{
+ "m_SGVersion": 0,
+ "m_Type": "UnityEditor.ShaderGraph.BlockNode",
+ "m_ObjectId": "54acbcd866754623a9971b65c87753b5",
+ "m_Group": {
+ "m_Id": ""
+ },
+ "m_Name": "VertexDescription.Normal",
+ "m_DrawState": {
+ "m_Expanded": true,
+ "m_Position": {
+ "serializedVersion": "2",
+ "x": 0.0,
+ "y": 0.0,
+ "width": 0.0,
+ "height": 0.0
+ }
+ },
+ "m_Slots": [
+ {
+ "m_Id": "bdebc5a760f846638151adf9af8840ef"
+ }
+ ],
+ "synonyms": [],
+ "m_Precision": 0,
+ "m_PreviewExpanded": true,
+ "m_DismissedVersion": 0,
+ "m_PreviewMode": 0,
+ "m_CustomColors": {
+ "m_SerializableColors": []
+ },
+ "m_SerializedDescriptor": "VertexDescription.Normal"
+}
+
+{
+ "m_SGVersion": 0,
+ "m_Type": "UnityEditor.ShaderGraph.CategoryData",
+ "m_ObjectId": "5b7e26a64997477b8fceed79720cbe18",
+ "m_Name": "",
+ "m_ChildObjectList": [
+ {
+ "m_Id": "3ba9df8d7b064813844ee1a01ff30884"
+ }
+ ]
+}
+
+{
+ "m_SGVersion": 0,
+ "m_Type": "UnityEditor.ShaderGraph.ColorRGBMaterialSlot",
+ "m_ObjectId": "5c5be1888bc54fd2b3729d265949c03d",
+ "m_Id": 0,
+ "m_DisplayName": "Base Color",
+ "m_SlotType": 0,
+ "m_Hidden": false,
+ "m_ShaderOutputName": "BaseColor",
+ "m_StageCapability": 2,
+ "m_Value": {
+ "x": 0.5,
+ "y": 0.5,
+ "z": 0.5
+ },
+ "m_DefaultValue": {
+ "x": 0.0,
+ "y": 0.0,
+ "z": 0.0
+ },
+ "m_Labels": [],
+ "m_ColorMode": 0,
+ "m_DefaultColor": {
+ "r": 0.5,
+ "g": 0.5,
+ "b": 0.5,
+ "a": 1.0
+ }
+}
+
+{
+ "m_SGVersion": 0,
+ "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot",
+ "m_ObjectId": "65e0744788694ef2a6997127e52e86df",
+ "m_Id": 0,
+ "m_DisplayName": "RGBA",
+ "m_SlotType": 1,
+ "m_Hidden": false,
+ "m_ShaderOutputName": "RGBA",
+ "m_StageCapability": 2,
+ "m_Value": {
+ "x": 0.0,
+ "y": 0.0,
+ "z": 0.0,
+ "w": 0.0
+ },
+ "m_DefaultValue": {
+ "x": 0.0,
+ "y": 0.0,
+ "z": 0.0,
+ "w": 0.0
+ },
+ "m_Labels": []
+}
+
+{
+ "m_SGVersion": 2,
+ "m_Type": "UnityEditor.Rendering.Universal.ShaderGraph.UniversalUnlitSubTarget",
+ "m_ObjectId": "82a2f491e31c4a83a8bfa01a377c3b68"
+}
+
+{
+ "m_SGVersion": 0,
+ "m_Type": "UnityEditor.ShaderGraph.PropertyNode",
+ "m_ObjectId": "8346d6ed11034b1785db95ef2e8bf371",
+ "m_Group": {
+ "m_Id": ""
+ },
+ "m_Name": "Property",
+ "m_DrawState": {
+ "m_Expanded": true,
+ "m_Position": {
+ "serializedVersion": "2",
+ "x": 397.9999694824219,
+ "y": -323.3333435058594,
+ "width": 166.66665649414063,
+ "height": 33.99998474121094
+ }
+ },
+ "m_Slots": [
+ {
+ "m_Id": "9314c3adf5944d85aecd153224b0d052"
+ }
+ ],
+ "synonyms": [],
+ "m_Precision": 0,
+ "m_PreviewExpanded": true,
+ "m_DismissedVersion": 0,
+ "m_PreviewMode": 0,
+ "m_CustomColors": {
+ "m_SerializableColors": []
+ },
+ "m_Property": {
+ "m_Id": "3ba9df8d7b064813844ee1a01ff30884"
+ }
+}
+
+{
+ "m_SGVersion": 0,
+ "m_Type": "UnityEditor.ShaderGraph.SampleTexture2DNode",
+ "m_ObjectId": "8d0d097456884c839b0e1bccbd948c83",
+ "m_Group": {
+ "m_Id": ""
+ },
+ "m_Name": "Sample Texture 2D",
+ "m_DrawState": {
+ "m_Expanded": true,
+ "m_Position": {
+ "serializedVersion": "2",
+ "x": 579.9999389648438,
+ "y": -363.9999694824219,
+ "width": 186.66668701171876,
+ "height": 250.66668701171876
+ }
+ },
+ "m_Slots": [
+ {
+ "m_Id": "65e0744788694ef2a6997127e52e86df"
+ },
+ {
+ "m_Id": "fc04b5e5ba934388a44813680a77fbcc"
+ },
+ {
+ "m_Id": "012c063cd77b4055a5d02d510505e55e"
+ },
+ {
+ "m_Id": "1bd6c17f30d843c5bded4563c487ef31"
+ },
+ {
+ "m_Id": "3e6a598eb5204f6287316d0d3809b215"
+ },
+ {
+ "m_Id": "c81c4d76704d4e9abb6058defef68892"
+ },
+ {
+ "m_Id": "dffb325305ee488f981ffcfee4bbe1fa"
+ },
+ {
+ "m_Id": "5186d854ec8f4e55a948afefab209f95"
+ }
+ ],
+ "synonyms": [],
+ "m_Precision": 0,
+ "m_PreviewExpanded": false,
+ "m_DismissedVersion": 0,
+ "m_PreviewMode": 0,
+ "m_CustomColors": {
+ "m_SerializableColors": []
+ },
+ "m_TextureType": 0,
+ "m_NormalMapSpace": 1,
+ "m_EnableGlobalMipBias": true,
+ "m_MipSamplingMode": 0
+}
+
+{
+ "m_SGVersion": 0,
+ "m_Type": "UnityEditor.ShaderGraph.Texture2DMaterialSlot",
+ "m_ObjectId": "9314c3adf5944d85aecd153224b0d052",
+ "m_Id": 0,
+ "m_DisplayName": "LowResTexture",
+ "m_SlotType": 1,
+ "m_Hidden": false,
+ "m_ShaderOutputName": "Out",
+ "m_StageCapability": 3,
+ "m_BareResource": false
+}
+
+{
+ "m_SGVersion": 0,
+ "m_Type": "UnityEditor.ShaderGraph.TangentMaterialSlot",
+ "m_ObjectId": "95d25e4d952f48c38ba5e62dc3fab9cd",
+ "m_Id": 0,
+ "m_DisplayName": "Tangent",
+ "m_SlotType": 0,
+ "m_Hidden": false,
+ "m_ShaderOutputName": "Tangent",
+ "m_StageCapability": 1,
+ "m_Value": {
+ "x": 0.0,
+ "y": 0.0,
+ "z": 0.0
+ },
+ "m_DefaultValue": {
+ "x": 0.0,
+ "y": 0.0,
+ "z": 0.0
+ },
+ "m_Labels": [],
+ "m_Space": 0
+}
+
+{
+ "m_SGVersion": 0,
+ "m_Type": "UnityEditor.ShaderGraph.BlockNode",
+ "m_ObjectId": "b646594906c747a4a535fe5a190c267e",
+ "m_Group": {
+ "m_Id": ""
+ },
+ "m_Name": "SurfaceDescription.BaseColor",
+ "m_DrawState": {
+ "m_Expanded": true,
+ "m_Position": {
+ "serializedVersion": "2",
+ "x": 0.0,
+ "y": 0.0,
+ "width": 0.0,
+ "height": 0.0
+ }
+ },
+ "m_Slots": [
+ {
+ "m_Id": "5c5be1888bc54fd2b3729d265949c03d"
+ }
+ ],
+ "synonyms": [],
+ "m_Precision": 0,
+ "m_PreviewExpanded": true,
+ "m_DismissedVersion": 0,
+ "m_PreviewMode": 0,
+ "m_CustomColors": {
+ "m_SerializableColors": []
+ },
+ "m_SerializedDescriptor": "SurfaceDescription.BaseColor"
+}
+
+{
+ "m_SGVersion": 0,
+ "m_Type": "UnityEditor.ShaderGraph.NormalMaterialSlot",
+ "m_ObjectId": "bdebc5a760f846638151adf9af8840ef",
+ "m_Id": 0,
+ "m_DisplayName": "Normal",
+ "m_SlotType": 0,
+ "m_Hidden": false,
+ "m_ShaderOutputName": "Normal",
+ "m_StageCapability": 1,
+ "m_Value": {
+ "x": 0.0,
+ "y": 0.0,
+ "z": 0.0
+ },
+ "m_DefaultValue": {
+ "x": 0.0,
+ "y": 0.0,
+ "z": 0.0
+ },
+ "m_Labels": [],
+ "m_Space": 0
+}
+
+{
+ "m_SGVersion": 0,
+ "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot",
+ "m_ObjectId": "c81c4d76704d4e9abb6058defef68892",
+ "m_Id": 1,
+ "m_DisplayName": "Texture",
+ "m_SlotType": 0,
+ "m_Hidden": false,
+ "m_ShaderOutputName": "Texture",
+ "m_StageCapability": 3,
+ "m_BareResource": false,
+ "m_Texture": {
+ "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}",
+ "m_Guid": ""
+ },
+ "m_DefaultType": 0
+}
+
+{
+ "m_SGVersion": 0,
+ "m_Type": "UnityEditor.ShaderGraph.UVMaterialSlot",
+ "m_ObjectId": "dffb325305ee488f981ffcfee4bbe1fa",
+ "m_Id": 2,
+ "m_DisplayName": "UV",
+ "m_SlotType": 0,
+ "m_Hidden": false,
+ "m_ShaderOutputName": "UV",
+ "m_StageCapability": 3,
+ "m_Value": {
+ "x": 0.0,
+ "y": 0.0
+ },
+ "m_DefaultValue": {
+ "x": 0.0,
+ "y": 0.0
+ },
+ "m_Labels": [],
+ "m_Channel": 0
+}
+
+{
+ "m_SGVersion": 0,
+ "m_Type": "UnityEditor.ShaderGraph.BlockNode",
+ "m_ObjectId": "e89eafddf99b406dba0daa5373d685ee",
+ "m_Group": {
+ "m_Id": ""
+ },
+ "m_Name": "VertexDescription.Position",
+ "m_DrawState": {
+ "m_Expanded": true,
+ "m_Position": {
+ "serializedVersion": "2",
+ "x": -81.33334350585938,
+ "y": -847.3334350585938,
+ "width": 200.0,
+ "height": 40.66668701171875
+ }
+ },
+ "m_Slots": [
+ {
+ "m_Id": "4da2c55cfe2e4cf9a6659081084573f0"
+ }
+ ],
+ "synonyms": [],
+ "m_Precision": 0,
+ "m_PreviewExpanded": true,
+ "m_DismissedVersion": 0,
+ "m_PreviewMode": 0,
+ "m_CustomColors": {
+ "m_SerializableColors": []
+ },
+ "m_SerializedDescriptor": "VertexDescription.Position"
+}
+
+{
+ "m_SGVersion": 0,
+ "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot",
+ "m_ObjectId": "fc04b5e5ba934388a44813680a77fbcc",
+ "m_Id": 4,
+ "m_DisplayName": "R",
+ "m_SlotType": 1,
+ "m_Hidden": false,
+ "m_ShaderOutputName": "R",
+ "m_StageCapability": 2,
+ "m_Value": 0.0,
+ "m_DefaultValue": 0.0,
+ "m_Labels": []
+}
+
diff --git a/Assets/3DPixelCamera/URP/UpscaleShaderURP.shadergraph.meta b/Assets/3DPixelCamera/URP/UpscaleShaderURP.shadergraph.meta
new file mode 100644
index 000000000..811b5fdfe
--- /dev/null
+++ b/Assets/3DPixelCamera/URP/UpscaleShaderURP.shadergraph.meta
@@ -0,0 +1,10 @@
+fileFormatVersion: 2
+guid: c63d04c1c20ea83498addf7813ae3dc5
+ScriptedImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 2
+ userData:
+ assetBundleName:
+ assetBundleVariant:
+ script: {fileID: 11500000, guid: 625f186215c104763be7675aa2d941aa, type: 3}
diff --git a/Assets/WL/Combat/Settings/Resources/WL/WLPixelCameraSettings.asset b/Assets/WL/Combat/Settings/Resources/WL/WLPixelCameraSettings.asset
new file mode 100644
index 000000000..d4cecf9ba
--- /dev/null
+++ b/Assets/WL/Combat/Settings/Resources/WL/WLPixelCameraSettings.asset
@@ -0,0 +1,39 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!114 &11400000
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 0}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: aedb96845e568d44889723065b993c14, type: 3}
+ m_Name: WLPixelCameraSettings
+ m_EditorClassIdentifier: Assembly-CSharp::WL.PixelArt.WLPixelCameraSettings
+ enabled: 1
+ verboseLog: 0
+ assembleOnMapEnter: 1
+ assembleInLobby: 0
+ pollSeconds: 0.25
+ pixelCameraSystemPrefab: {fileID: 2255326839739188927, guid: e96cffa9d00b6b545adfeb26165952cc,
+ type: 3}
+ rigLayer: 31
+ proxyMode: 0
+ orthoSize: 3.8
+ pixelHeight: 480
+ compensateViewZoom: 1
+ voxelGridMovement: 1
+ subpixelAdjustments: 1
+ followRotation: 1
+ controlGameZoom: 1
+ viewCameraZoom: 1
+ viewCameraInMainStack: 1
+ disableSnapWhileRotating: 1
+ rotationSnapOffDegPerSec: 30
+ rotationSnapResumeSeconds: 0.25
+ mainCameraCullingMask: 0
+ mainCameraPostProcessingOff: 1
+ copyPostProcessingToGameCamera: 1
+ mainCameraSolidBlack: 1
diff --git a/Assets/WL/Combat/Settings/Resources/WL/WLPixelCameraSettings.asset.meta b/Assets/WL/Combat/Settings/Resources/WL/WLPixelCameraSettings.asset.meta
new file mode 100644
index 000000000..5b42f5f2c
--- /dev/null
+++ b/Assets/WL/Combat/Settings/Resources/WL/WLPixelCameraSettings.asset.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 6b6db3e9a69baba4381dc38c3c2c414f
+NativeFormatImporter:
+ externalObjects: {}
+ mainObjectFileID: 11400000
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/WL/PixelCamera.meta b/Assets/WL/PixelCamera.meta
new file mode 100644
index 000000000..e40cbf426
--- /dev/null
+++ b/Assets/WL/PixelCamera.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 7bcfe795ab749ec4bad536c992cb5e70
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/WL/PixelCamera/PixelCameraRig.cs b/Assets/WL/PixelCamera/PixelCameraRig.cs
new file mode 100644
index 000000000..ecca6b8ca
--- /dev/null
+++ b/Assets/WL/PixelCamera/PixelCameraRig.cs
@@ -0,0 +1,711 @@
+// ─────────────────────────────────────────────────────────────────────────────
+// PixelCameraRig.cs — Critter 3D Pixel Camera 를 인게임에서 런타임 조립/복원하는 WL 리그
+//
+// PD 지시 #814(「Critter 3D Pixel Art Toolkit 으로 도트 게임처럼」) · 발주서 WL-814b §1-3
+//
+// ■ 왜 이렇게 만들었나 (실측 근거 — 보고서 표 ①)
+// · 원본 인게임 카메라는 `Assets/ResWork/Prefabs/Ingame/Main Camera.prefab`(tag MainCamera · fov 60 · 원근)이고
+// `Assets/Script/Util/RealCamera.cs` 가 **LateUpdate 에서** 트랜스폼을 쓴다. CamStatus 1/2 는
+// `Vector3.Lerp(transform.position, …)` = **현재 위치에서 보간**이라 누가 카메라 트랜스폼에 되쓰면
+// 그 값이 다음 프레임의 입력이 된다(피드백 루프). → 리그는 카메라 트랜스폼에 **절대 쓰지 않는다**.
+// · `RealCamera.Shaking()` 은 `transform.localPosition` 을 쓴다(811gh 셰이크). 원본 카메라를 **재부모화하면
+// 셰이크 기준이 깨진다** → 재부모화 0. 대신 **원본 카메라의 자식**으로 빈 프록시를 하나 달아
+// Critter 가 그것을 따라가게 한다(지연 0 · 프레임당 비용 0 · 셰이크도 그대로 미러된다).
+// · `MyValue.m_RealCamera` 는 `Camera.main.GetComponent()` 다 → 원본 카메라가 **계속
+// MainCamera 태그를 달고 enabled 여야** 한다(`Camera.main` 은 활성 카메라만 돌려준다).
+// · 인게임 UI 캔버스는 **Screen Space - Camera(UICamera)** 이고 `NewGameUI.cs:38` 이 그 UICamera 를
+// **`Camera.main` 의 URP 카메라 스택에 Overlay 로** 넣는다 → 원본 카메라를 끄면 UI 가 사라진다.
+// 그래서 원본 카메라는 화면 Base 로 남기고, Critter 뷰 카메라를 같은 스택의 **0번 Overlay** 로 끼운다.
+// 스택 = [원본 Main Camera(Base · 월드 미렌더)] → [ViewCamera(Overlay · 픽셀 쿼드)] → [UICamera(Overlay · UI)]
+// · `HUDBase.cs:28,55`(HP 바 · 데미지 숫자)와 `DSUtil.cs:859`·`InGameTouchInfo.cs:37` 은 전부
+// `Camera.main` 의 투영을 쓴다 → 원본 카메라를 **직교로 바꿔** 픽셀 카메라와 같은 투영을 갖게 한다.
+//
+// ■ 리그 구조 (Assemble 이 만든다 · 디스크 에셋 수정 0)
+// WL_PixelCameraRig = PixelCameraSystem.prefab 인스턴스(루트 이름만 바꿈)
+// ├─ PixelCameraTransform 프리팹 기본 followed(ChildOfCamera 모드에서는 쓰지 않는다 · 삭제하면
+// │ Critter 의 `parent.childCount` 권고에서 벗어나므로 그대로 둔다)
+// └─ PixelCamera 직교 카메라 + PixelCameraManager · 저해상도 RT 로 월드를 그린다
+// └─ UpscaledDisplay
+// ├─ QuadCanvas RT 를 붙인 쿼드(UpscaledCanvas) · rigLayer
+// └─ ViewCamera 직교 · CanvasViewCamera(서브픽셀 보정) · rigLayer 만 그린다
+// Main Camera (원본 · 트랜스폼 무변경)
+// └─ WL_PixelFollow 프록시(빈 오브젝트 · localPos 0 · localRot identity)
+//
+// ■ C8 롤백
+// `WLPixelCameraSettings.enabled = 0`(또는 `RuntimeDisabled`) → 다음 틱에 Teardown → 원본 카메라 값
+// (직교/사이즈/컬링/클리어/배경/near·far/fov/depth/포스트/스택)이 **스냅샷 그대로** 복원되고 리그 오브젝트 0 · RT 해제.
+//
+// 🔴 이 파일은 Debug.LogError / Debug.LogException 을 쓰지 않는다(813z · ErrorLogHookManager 팝업).
+// 🔴 Assets/WL/ 에 .asmdef 를 만들지 말 것.
+// ─────────────────────────────────────────────────────────────────────────────
+
+using UnityEngine;
+using UnityEngine.Rendering.Universal;
+using PixelCamera;
+
+namespace WL.PixelArt
+{
+ /// Critter 픽셀 카메라 리그의 조립·복원. 정적 · 전용 러너 1개.
+ public static class PixelCameraRig
+ {
+ public const string RigName = "WL_PixelCameraRig";
+ public const string ProxyName = "WL_PixelFollow";
+
+ // ───────────────────────────────────────── 진단(프로브가 읽는다)
+ public static int Boundaries, Assembled, Restored, SkippedLobby, SkippedNoCam, SkippedNoPrefab, Faults;
+ public static string LastReason = "", LastLog = "";
+
+ /// 지금 리그가 조립돼 있는가.
+ public static bool IsAssembled { get { return s_rigRoot != null; } }
+
+ /// 조립된 리그의 핵심 참조(프로브 전용).
+ public static GameObject RigRoot { get { return s_rigRoot; } }
+ public static Camera SourceCamera { get { return s_src; } }
+ public static Camera GameCamera { get { return s_gameCam; } }
+ public static Camera ViewCamera { get { return s_viewCam; } }
+ public static Transform Proxy { get { return s_proxy; } }
+ public static PixelCameraManager Manager { get { return s_mgr; } }
+
+ /// 지금 회전 때문에 스냅이 꺼져 있는가(진단).
+ public static bool SnapSuspended { get { return s_snapSuspended; } }
+
+ // ───────────────────────────────────────── 내부 상태
+ static Camera s_src;
+ static GameObject s_rigRoot, s_proxyGo;
+ static Transform s_proxy;
+ static Camera s_gameCam, s_viewCam;
+ static PixelCameraManager s_mgr;
+ static UpscaledCanvas s_canvas;
+ static Material s_matInstance;
+ static MeshRenderer s_quadRenderer;
+ static Material s_quadSharedMat;
+
+ static CamSnapshot s_snap;
+ static bool s_faulted;
+
+ static PCActor s_lastPc;
+ static int s_lastMapId = int.MinValue;
+ static float s_nextPoll;
+
+ static bool s_snapSuspended;
+ static float s_snapResumeAt;
+ static Quaternion s_lastSrcRot = Quaternion.identity;
+ static bool s_hasLastRot;
+
+ static WLPixelCameraSettings Cfg { get { return WLPixelCameraSettings.Instance; } }
+ static bool Active { get { return WLPixelCameraSettings.Enabled; } }
+
+ // ─────────────────────────────────────────────────────────────────────
+ // 틱 (러너가 매 프레임 부른다 · 에디트 모드에서는 프로브가 직접 부를 수 있다)
+ // ─────────────────────────────────────────────────────────────────────
+
+ /// 1프레임. (프로브가 별도 어셈블리에서 부르므로 public)
+ public static void Tick()
+ {
+ if (s_faulted) return;
+
+ // C8 — 기능이 꺼지면 즉시 원상복구.
+ if (!Active) { if (IsAssembled) Teardown("off"); return; }
+
+ try
+ {
+ var cfg = Cfg;
+ UpdateSnapSuspension(cfg);
+
+ float now = Time.unscaledTime;
+ if (now < s_nextPoll) return;
+ s_nextPoll = now + Mathf.Max(0.02f, cfg.pollSeconds);
+ if (cfg.assembleOnMapEnter) PollBoundary(cfg);
+ }
+ catch (System.Exception ex)
+ {
+ s_faulted = true; Faults++;
+ LastLog = "중단(예외) — " + ex.Message;
+ Log(LastLog); // 🔴 LogError 금지(813z)
+ }
+ }
+
+ /// 맵 진입/이탈 경계 — 811q EffectWarmup · 811o CameraFramingOverride 와 같은 규칙.
+ static void PollBoundary(WLPixelCameraSettings cfg)
+ {
+ if (!Application.isPlaying) return; // 에디트 모드 오염 0(프로브는 ProbeAssemble 로 들어온다)
+
+ var pc = MyValue.MyPC;
+ if (DSUtil.CheckNull(pc))
+ {
+ // 맵 이탈 — PC 가 사라졌다. 리그를 걷는다.
+ if (s_lastPc != null && IsAssembled) Teardown("맵 이탈");
+ s_lastPc = null;
+ return;
+ }
+
+ var info = InGameInfo.Ins;
+ if (DSUtil.CheckNull(info)) return; // 인게임 정보가 아직 없다 — 경계를 소비하지 않는다
+
+ int map = MyValue.MyChoiceMapData != null ? MyValue.MyChoiceMapData.n_MapID : int.MinValue;
+ bool pcChanged = !ReferenceEquals(pc, s_lastPc);
+ bool mapChanged = map != s_lastMapId;
+ if (!pcChanged && !mapChanged) return;
+
+ bool lobby = info.Get_GameMode() == eGameMode.Lobby;
+ if (!cfg.assembleInLobby && lobby)
+ {
+ s_lastPc = pc; s_lastMapId = map;
+ Boundaries++; SkippedLobby++;
+ LastReason = "lobby";
+ if (IsAssembled) Teardown("로비 진입");
+ return;
+ }
+
+ var cam = Camera.main;
+ if (cam == null) { SkippedNoCam++; return; } // 경계를 소비하지 않는다 — 다음 폴링에서 다시 본다
+
+ s_lastPc = pc; s_lastMapId = map;
+ Boundaries++;
+ LastReason = pcChanged ? "pc" : ("map " + map);
+
+ if (IsAssembled) Teardown("경계 재조립");
+ Assemble(cfg, cam);
+ }
+
+ // ─────────────────────────────────────────────────────────────────────
+ // 조립
+ // ─────────────────────────────────────────────────────────────────────
+
+ /// 리그를 조립한다. 성공 시 true.
+ public static bool Assemble(WLPixelCameraSettings cfg, Camera src)
+ {
+ if (cfg == null || src == null) return false;
+ if (IsAssembled) return true;
+
+ var prefab = cfg.pixelCameraSystemPrefab;
+ if (prefab == null)
+ {
+ SkippedNoPrefab++;
+ LastLog = "PixelCameraSystem 프리팹 미설정 — 조립 안 함(URP.unitypackage 해제 확인)";
+ Log(LastLog);
+ return false;
+ }
+
+ // 이전 잔재(에디트 모드 재실행 등) 제거 — Critter 의 FindAnyObjectByType 가 엉뚱한 걸 잡지 않게.
+ DestroyStrays();
+
+ s_src = src;
+ s_snap.Capture(src);
+
+ // ── 리그 인스턴스. 프리팹이 followed/뷰/캔버스를 이미 배선해 두었으므로 활성 상태로 만들어
+ // Critter Initialize() 의 LogError 경로(부모 없음 · followed null · 뷰/캔버스 못 찾음)를 전부 피한다.
+ // 값 보정은 같은 프레임 안에서 끝나므로(LateUpdate 이전) 잘못된 프레임이 그려지지 않는다.
+ s_rigRoot = Object.Instantiate(prefab);
+ s_rigRoot.name = RigName;
+ s_rigRoot.transform.SetPositionAndRotation(src.transform.position, src.transform.rotation);
+
+ s_mgr = s_rigRoot.GetComponentInChildren(true);
+ var view = s_rigRoot.GetComponentInChildren(true);
+ s_canvas = s_rigRoot.GetComponentInChildren(true);
+ if (s_mgr == null || view == null || s_canvas == null)
+ {
+ LastLog = "리그 프리팹 구조가 예상과 다르다 — 조립 취소";
+ Log(LastLog);
+ Teardown("구조 불일치");
+ Faults++;
+ return false;
+ }
+
+ s_gameCam = s_mgr.GetComponent();
+ s_viewCam = view.GetComponent();
+ if (s_gameCam == null || s_viewCam == null)
+ {
+ LastLog = "리그 카메라 컴포넌트 없음 — 조립 취소";
+ Log(LastLog);
+ Teardown("카메라 없음");
+ Faults++;
+ return false;
+ }
+
+ // 🔴 Critter 프리팹의 ViewCamera 에는 AudioListener 가 달려 있다(실측). 원본 Main Camera 의 것과
+ // 겹치면 Unity 가 "There are 2 audio listeners in the scene" 경고를 매 프레임 낸다 → 리그 것은 끈다.
+ var listeners = s_rigRoot.GetComponentsInChildren(true);
+ for (int i = 0; i < listeners.Length; i++) if (listeners[i] != null) DestroyObj(listeners[i]);
+
+ int layer = Mathf.Clamp(cfg.rigLayer, 0, 31);
+ SetLayerRecursive(s_rigRoot.transform, layer);
+ s_rigRoot.tag = "Untagged";
+ s_gameCam.gameObject.tag = "Untagged";
+ s_viewCam.gameObject.tag = "Untagged";
+
+ // ── 쿼드 머티리얼을 런타임 인스턴스로 갈아 끼운다.
+ // Critter 의 UpscaledCanvas 는 sharedMaterial 에 _LowResTexture 를 직접 SetTexture 한다 →
+ // 그대로 두면 **디스크의 .mat 에셋이 더러워진다**(에디트 모드에서 특히). 인스턴스로 바꾸고
+ // OnEnable 을 다시 돌려 캐시를 갱신한다.
+ s_quadRenderer = s_canvas.GetComponent();
+ if (s_quadRenderer != null && s_quadRenderer.sharedMaterial != null)
+ {
+ s_quadSharedMat = s_quadRenderer.sharedMaterial;
+ s_matInstance = new Material(s_quadSharedMat);
+ s_matInstance.name = s_quadSharedMat.name + " (WL rig runtime)";
+ s_quadRenderer.sharedMaterial = s_matInstance;
+ s_canvas.enabled = false; s_canvas.enabled = true; // OnEnable 재실행 → 인스턴스 캐시
+ }
+
+ // ── 프록시
+ if (cfg.proxyMode == PixelProxyMode.ChildOfCamera)
+ {
+ s_proxyGo = new GameObject(ProxyName);
+ s_proxyGo.layer = layer;
+ s_proxyGo.transform.SetParent(src.transform, false);
+ s_proxyGo.transform.localPosition = Vector3.zero;
+ s_proxyGo.transform.localRotation = Quaternion.identity;
+ s_proxyGo.transform.localScale = Vector3.one;
+ s_proxy = s_proxyGo.transform;
+ }
+ else
+ {
+ s_proxyGo = new GameObject(ProxyName);
+ s_proxyGo.layer = layer;
+ s_proxyGo.transform.SetPositionAndRotation(src.transform.position, src.transform.rotation);
+ var mirror = s_proxyGo.AddComponent();
+ mirror.Source = src.transform;
+ s_proxy = s_proxyGo.transform;
+ }
+
+ // ── 저해상도 게임 카메라 = 원본이 보던 월드를 그대로 본다(리그 레이어만 뺀다)
+ s_gameCam.orthographic = true;
+ s_gameCam.nearClipPlane = s_snap.near;
+ s_gameCam.farClipPlane = s_snap.far;
+ s_gameCam.cullingMask = s_snap.cullingMask & ~(1 << layer);
+ s_gameCam.clearFlags = s_snap.clearFlags;
+ s_gameCam.backgroundColor = s_snap.background;
+ s_gameCam.allowHDR = s_snap.allowHDR;
+ s_gameCam.allowMSAA = s_snap.allowMSAA;
+ s_gameCam.useOcclusionCulling = s_snap.occlusionCulling;
+ s_gameCam.depth = s_snap.depth - 1f; // 원본(화면 Base)보다 먼저 RT 를 채운다
+ s_gameCam.targetTexture = null; // Critter 가 만든다
+
+ var srcData = s_src.GetUniversalAdditionalCameraData();
+ var gameData = s_gameCam.GetUniversalAdditionalCameraData();
+ if (gameData != null)
+ {
+ gameData.renderType = CameraRenderType.Base;
+ if (gameData.cameraStack != null) gameData.cameraStack.Clear();
+ if (srcData != null)
+ {
+ gameData.renderShadows = srcData.renderShadows;
+ gameData.volumeLayerMask = srcData.volumeLayerMask;
+ gameData.volumeTrigger = srcData.volumeTrigger;
+ gameData.renderPostProcessing = cfg.copyPostProcessingToGameCamera && srcData.renderPostProcessing;
+ gameData.antialiasing = srcData.antialiasing;
+ gameData.antialiasingQuality = srcData.antialiasingQuality;
+ gameData.stopNaN = srcData.stopNaN;
+ gameData.dithering = srcData.dithering;
+ }
+ }
+
+ // ── Critter 값
+ float aspect = ScreenAspect();
+ int px = Mathf.Max(3, cfg.pixelHeight);
+ s_mgr.FollowedTransform = s_proxy;
+ s_mgr.VoxelGridMovement = cfg.voxelGridMovement;
+ s_mgr.SubpixelAdjustments = cfg.subpixelAdjustments;
+ s_mgr.FollowRotation = cfg.followRotation;
+ s_mgr.resolutionSynchronizationMode = ResolutionSynchronizationMode.SetHeight;
+ s_mgr.GameResolution = new Vector2Int(Mathf.Max(2, Mathf.RoundToInt(px * aspect)), px);
+ s_mgr.ControlGameZoom = cfg.controlGameZoom;
+ s_mgr.GameCameraZoom = GameZoomFor(cfg);
+ s_mgr.ViewCameraZoom = cfg.viewCameraZoom;
+
+ // ── 뷰 카메라 = 픽셀 쿼드만 그린다
+ s_viewCam.orthographic = true;
+ s_viewCam.cullingMask = 1 << layer;
+ s_viewCam.allowHDR = s_snap.allowHDR;
+ s_viewCam.allowMSAA = false;
+ s_viewCam.useOcclusionCulling = false;
+ var viewData = s_viewCam.GetUniversalAdditionalCameraData();
+ if (viewData != null)
+ {
+ viewData.renderPostProcessing = false;
+ viewData.renderShadows = false;
+ viewData.renderType = cfg.viewCameraInMainStack ? CameraRenderType.Overlay : CameraRenderType.Base;
+ if (viewData.cameraStack != null && viewData.renderType == CameraRenderType.Base) viewData.cameraStack.Clear();
+ }
+ if (!cfg.viewCameraInMainStack) s_viewCam.depth = s_snap.depth + 1f;
+
+ // ── 원본 카메라 = 화면 Base 로 남되 월드는 그리지 않는다(투영만 픽셀 카메라와 맞춘다)
+ s_src.orthographic = true;
+ s_src.orthographicSize = cfg.orthoSize;
+ s_src.cullingMask = cfg.mainCameraCullingMask;
+ if (cfg.mainCameraSolidBlack)
+ {
+ s_src.clearFlags = CameraClearFlags.SolidColor;
+ s_src.backgroundColor = Color.black;
+ }
+ if (srcData != null)
+ {
+ if (cfg.mainCameraPostProcessingOff) srcData.renderPostProcessing = false;
+ srcData.renderShadows = false;
+ if (cfg.viewCameraInMainStack && srcData.cameraStack != null)
+ srcData.cameraStack.Insert(0, s_viewCam); // ViewCamera → UICamera 순서
+ }
+
+ Assembled++;
+ s_hasLastRot = false;
+ s_snapSuspended = false;
+ LastLog = "조립 — ortho " + cfg.orthoSize.ToString("0.###")
+ + " · RT " + s_mgr.GameResolution.x + "×" + s_mgr.GameResolution.y
+ + " · zoom " + s_mgr.GameCameraZoom.ToString("0.####")
+ + " · layer " + layer;
+ Log(LastLog);
+ return true;
+ }
+
+ /// SO 값으로 Critter 게임 카메라 줌(= 캔버스 반높이)을 계산한다.
+ public static float GameZoomFor(WLPixelCameraSettings cfg)
+ {
+ if (cfg == null) return 5f;
+ if (!cfg.compensateViewZoom) return cfg.orthoSize;
+ return cfg.orthoSize / CanvasOnScreenLimit(cfg.pixelHeight);
+ }
+
+ /// Critter 가 캔버스 가장자리를 넘지 않으려고 쓰는 줌 한계 = 1 − 2/pixelHeight.
+ public static float CanvasOnScreenLimit(int pixelHeight)
+ {
+ int py = Mathf.Max(3, pixelHeight);
+ return 1f - (2f / py);
+ }
+
+ static float ScreenAspect()
+ {
+ float w = Screen.width, h = Screen.height;
+ if (w <= 0f || h <= 0f) return 9f / 16f;
+ return w / h;
+ }
+
+ // ─────────────────────────────────────────────────────────────────────
+ // 복원
+ // ─────────────────────────────────────────────────────────────────────
+
+ /// 리그를 걷고 원본 카메라를 스냅샷 그대로 되돌린다.
+ public static void Teardown(string why)
+ {
+ bool had = s_rigRoot != null || s_proxyGo != null;
+
+ // 원본 카메라 복원 — 스택에서 뷰 카메라부터 뺀다.
+ if (s_src != null)
+ {
+ var srcData = s_src.GetUniversalAdditionalCameraData();
+ if (srcData != null && srcData.cameraStack != null)
+ {
+ srcData.cameraStack.Clear();
+ if (s_snap.stack != null)
+ for (int i = 0; i < s_snap.stack.Length; i++)
+ if (s_snap.stack[i] != null) srcData.cameraStack.Add(s_snap.stack[i]);
+ }
+ s_snap.Restore(s_src);
+ }
+
+ // RT 해제 — Critter 가 만든 것을 우리가 반납한다.
+ if (s_gameCam != null)
+ {
+ var rt = s_gameCam.targetTexture;
+ s_gameCam.targetTexture = null;
+ if (rt != null) { rt.Release(); DestroyObj(rt); }
+ }
+
+ // 쿼드 머티리얼 인스턴스 반납 + 원본 sharedMaterial 복귀(디스크 에셋 무변경 보장)
+ if (s_quadRenderer != null && s_quadSharedMat != null) s_quadRenderer.sharedMaterial = s_quadSharedMat;
+ if (s_matInstance != null) { DestroyObj(s_matInstance); s_matInstance = null; }
+
+ if (s_rigRoot != null) { DestroyObj(s_rigRoot); s_rigRoot = null; }
+ if (s_proxyGo != null) { DestroyObj(s_proxyGo); s_proxyGo = null; }
+ DestroyStrays();
+
+ s_proxy = null; s_gameCam = null; s_viewCam = null; s_mgr = null; s_canvas = null;
+ s_quadRenderer = null; s_quadSharedMat = null;
+ s_snapSuspended = false; s_hasLastRot = false;
+ s_src = null;
+
+ if (had)
+ {
+ Restored++;
+ LastLog = "복원 — " + why;
+ Log(LastLog);
+ }
+ }
+
+ /// 이름으로 남은 리그·프록시 잔재를 지운다(도메인 리로드·에디트 모드 재실행 대비).
+ static void DestroyStrays()
+ {
+ var all = Object.FindObjectsByType(FindObjectsInactive.Include, FindObjectsSortMode.None);
+ for (int i = 0; i < all.Length; i++)
+ {
+ if (all[i] == null) continue;
+ var root = all[i].transform.parent != null ? all[i].transform.parent.gameObject : all[i].gameObject;
+ if (root == s_rigRoot) continue;
+ if (root.name == RigName) DestroyObj(root);
+ }
+
+ // 프록시(원본 카메라의 자식)도 이름으로 정리
+ var cam = Camera.main;
+ if (cam != null)
+ {
+ for (int i = cam.transform.childCount - 1; i >= 0; i--)
+ {
+ var c = cam.transform.GetChild(i);
+ if (c != null && c.gameObject != s_proxyGo && c.name == ProxyName) DestroyObj(c.gameObject);
+ }
+ }
+ }
+
+ static void DestroyObj(Object o)
+ {
+ if (o == null) return;
+ if (Application.isPlaying) Object.Destroy(o);
+ else Object.DestroyImmediate(o);
+ }
+
+ static void SetLayerRecursive(Transform t, int layer)
+ {
+ t.gameObject.layer = layer;
+ for (int i = 0; i < t.childCount; i++) SetLayerRecursive(t.GetChild(i), layer);
+ }
+
+ // ─────────────────────────────────────────────────────────────────────
+ // 회전 중 스냅 해제 (Critter 문서 권고 · 811o 구도 전환 · 보스 연출)
+ // ─────────────────────────────────────────────────────────────────────
+
+ static void UpdateSnapSuspension(WLPixelCameraSettings cfg)
+ {
+ if (s_mgr == null || s_src == null) { s_hasLastRot = false; return; }
+ if (!cfg.disableSnapWhileRotating)
+ {
+ if (s_snapSuspended) { s_mgr.VoxelGridMovement = cfg.voxelGridMovement; s_mgr.SubpixelAdjustments = cfg.subpixelAdjustments; s_snapSuspended = false; }
+ return;
+ }
+
+ var rot = s_src.transform.rotation;
+ float dt = Mathf.Max(1e-4f, Time.unscaledDeltaTime);
+ if (!s_hasLastRot) { s_lastSrcRot = rot; s_hasLastRot = true; return; }
+
+ float degPerSec = Quaternion.Angle(s_lastSrcRot, rot) / dt;
+ s_lastSrcRot = rot;
+
+ float now = Time.unscaledTime;
+ if (degPerSec >= Mathf.Max(0f, cfg.rotationSnapOffDegPerSec))
+ {
+ s_snapResumeAt = now + Mathf.Max(0f, cfg.rotationSnapResumeSeconds);
+ if (!s_snapSuspended)
+ {
+ s_snapSuspended = true;
+ s_mgr.VoxelGridMovement = false;
+ s_mgr.SubpixelAdjustments = false;
+ }
+ }
+ else if (s_snapSuspended && now >= s_snapResumeAt)
+ {
+ s_snapSuspended = false;
+ s_mgr.VoxelGridMovement = cfg.voxelGridMovement;
+ s_mgr.SubpixelAdjustments = cfg.subpixelAdjustments;
+ }
+ }
+
+ // ─────────────────────────────────────────────────────────────────────
+ // 프로브 진입점
+ // ─────────────────────────────────────────────────────────────────────
+
+ /// 프로브·에디트 모드: 경계 폴링을 건너뛰고 지금 바로 조립한다.
+ public static bool ProbeAssemble(Camera src)
+ {
+ var cfg = Cfg;
+ if (cfg == null) return false;
+ if (IsAssembled) Teardown("probe 재조립");
+ return Assemble(cfg, src);
+ }
+
+ /// 프로브: 지금 바로 복원한다.
+ public static void ProbeTeardown() { Teardown("probe"); }
+
+ /// 프로브: 회전 스냅 판정을 1회 돌린다(에디트 모드).
+ public static void ProbeSnapTick() { var c = Cfg; if (c != null) UpdateSnapSuspension(c); }
+
+ /// 프로브: 원본 카메라 스냅샷을 한 줄로.
+ public static string SnapshotSummary() { return s_snap.Summary(); }
+
+ /// 프로브: 지금 원본 카메라 상태를 스냅샷과 같은 형식으로.
+ public static string CurrentSummary(Camera cam) { var s = new CamSnapshot(); s.Capture(cam); return s.Summary(); }
+
+ public static void ResetAll()
+ {
+ Teardown("reset");
+ Boundaries = Assembled = Restored = SkippedLobby = SkippedNoCam = SkippedNoPrefab = Faults = 0;
+ LastReason = LastLog = "";
+ s_faulted = false;
+ s_lastPc = null; s_lastMapId = int.MinValue; s_nextPoll = 0f;
+ }
+
+ static void Log(string msg)
+ {
+ var cfg = Cfg;
+ if (cfg != null && cfg.verboseLog) Debug.Log("[PixelCameraRig] " + msg);
+ }
+
+ // ─────────────────────────────────────────────────────────────────────
+ // 러너
+ // ─────────────────────────────────────────────────────────────────────
+
+ static GameObject s_runner;
+
+ [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)]
+ static void Boot()
+ {
+ if (s_runner != null) return;
+ if (!Active) return; // C8 — 러너 자체가 뜨지 않는다
+ s_runner = new GameObject("[WL814b] PixelCameraRigRunner");
+ s_runner.hideFlags = HideFlags.HideAndDontSave;
+ s_runner.AddComponent();
+ Object.DontDestroyOnLoad(s_runner);
+ }
+
+ internal static void OnRunnerQuit() { Teardown("quit"); }
+
+#if UNITY_EDITOR
+ /// 에디터: Play 진입/이탈 경계에서 반드시 복원한다(에디트 모드 프로브 잔재 0).
+ [UnityEditor.InitializeOnLoadMethod]
+ static void EditorHook()
+ {
+ UnityEditor.EditorApplication.playModeStateChanged -= OnPlayModeChanged;
+ UnityEditor.EditorApplication.playModeStateChanged += OnPlayModeChanged;
+ }
+
+ static void OnPlayModeChanged(UnityEditor.PlayModeStateChange s)
+ {
+ if (s == UnityEditor.PlayModeStateChange.ExitingEditMode || s == UnityEditor.PlayModeStateChange.ExitingPlayMode)
+ Teardown("playmode " + s);
+ }
+#endif
+ }
+
+ /// 매 프레임 리그 틱. Critter(기본 실행 순서 0)보다 먼저 돌아야 회전 스냅 해제가 그 프레임에 반영된다.
+ [DefaultExecutionOrder(-100)]
+ internal sealed class PixelCameraRigRunner : MonoBehaviour
+ {
+ void Update() { PixelCameraRig.Tick(); }
+ void OnApplicationQuit() { PixelCameraRig.OnRunnerQuit(); }
+ void OnDestroy() { PixelCameraRig.OnRunnerQuit(); }
+ }
+
+ /// MirrorScript 모드용 프록시. 원본 카메라 트랜스폼을 읽기만 한다(역방향 쓰기 0 = 피드백 루프 0).
+ [DefaultExecutionOrder(-100)]
+ public sealed class PixelCameraProxyMirror : MonoBehaviour
+ {
+ public Transform Source;
+
+ void LateUpdate()
+ {
+ if (Source == null) return;
+ transform.SetPositionAndRotation(Source.position, Source.rotation);
+ }
+
+ /// 프로브: 1회 미러(에디트 모드).
+ public void Mirror() { LateUpdate(); }
+ }
+
+ /// 원본 Camera + URP 데이터의 되돌릴 값 전부.
+ internal struct CamSnapshot
+ {
+ public bool valid;
+ public bool ortho;
+ public float orthoSize, fov, near, far, depth;
+ public int cullingMask;
+ public CameraClearFlags clearFlags;
+ public Color background;
+ public bool allowHDR, allowMSAA, occlusionCulling;
+ public RenderTexture target;
+
+ public bool hasData;
+ public CameraRenderType renderType;
+ public bool renderPost, renderShadows;
+ public LayerMask volumeMask;
+ public Transform volumeTrigger;
+ public AntialiasingMode aa;
+ public AntialiasingQuality aaQuality;
+ public Camera[] stack;
+
+ public void Capture(Camera c)
+ {
+ valid = c != null;
+ if (!valid) return;
+ ortho = c.orthographic; orthoSize = c.orthographicSize; fov = c.fieldOfView;
+ near = c.nearClipPlane; far = c.farClipPlane; depth = c.depth;
+ cullingMask = c.cullingMask; clearFlags = c.clearFlags; background = c.backgroundColor;
+ allowHDR = c.allowHDR; allowMSAA = c.allowMSAA; occlusionCulling = c.useOcclusionCulling;
+ target = c.targetTexture;
+
+ var d = c.GetUniversalAdditionalCameraData();
+ hasData = d != null;
+ if (!hasData) { stack = null; return; }
+ renderType = d.renderType;
+ renderPost = d.renderPostProcessing;
+ renderShadows = d.renderShadows;
+ volumeMask = d.volumeLayerMask;
+ volumeTrigger = d.volumeTrigger;
+ aa = d.antialiasing;
+ aaQuality = d.antialiasingQuality;
+
+ var st = d.cameraStack;
+ if (st == null) { stack = null; return; }
+ stack = new Camera[st.Count];
+ for (int i = 0; i < st.Count; i++) stack[i] = st[i];
+ }
+
+ public void Restore(Camera c)
+ {
+ if (!valid || c == null) return;
+ c.orthographic = ortho; c.orthographicSize = orthoSize; c.fieldOfView = fov;
+ c.nearClipPlane = near; c.farClipPlane = far; c.depth = depth;
+ c.cullingMask = cullingMask; c.clearFlags = clearFlags; c.backgroundColor = background;
+ c.allowHDR = allowHDR; c.allowMSAA = allowMSAA; c.useOcclusionCulling = occlusionCulling;
+ c.targetTexture = target;
+
+ if (!hasData) return;
+ var d = c.GetUniversalAdditionalCameraData();
+ if (d == null) return;
+ d.renderType = renderType;
+ d.renderPostProcessing = renderPost;
+ d.renderShadows = renderShadows;
+ d.volumeLayerMask = volumeMask;
+ d.volumeTrigger = volumeTrigger;
+ d.antialiasing = aa;
+ d.antialiasingQuality = aaQuality;
+ }
+
+ /// 비교용 한 줄 요약(프로브가 조립 전/후를 문자열로 대조한다).
+ public string Summary()
+ {
+ if (!valid) return "(none)";
+ var sb = new System.Text.StringBuilder(160);
+ sb.Append("ortho=").Append(ortho ? 1 : 0)
+ .Append(" size=").Append(orthoSize.ToString("0.####"))
+ .Append(" fov=").Append(fov.ToString("0.###"))
+ .Append(" near=").Append(near.ToString("0.###"))
+ .Append(" far=").Append(far.ToString("0.#"))
+ .Append(" depth=").Append(depth.ToString("0.##"))
+ .Append(" mask=").Append(cullingMask)
+ .Append(" clear=").Append((int)clearFlags)
+ .Append(" bg=").Append(background.r.ToString("0.###")).Append(',').Append(background.g.ToString("0.###")).Append(',').Append(background.b.ToString("0.###")).Append(',').Append(background.a.ToString("0.###"))
+ .Append(" hdr=").Append(allowHDR ? 1 : 0)
+ .Append(" msaa=").Append(allowMSAA ? 1 : 0)
+ .Append(" occ=").Append(occlusionCulling ? 1 : 0)
+ .Append(" rt=").Append(target == null ? 0 : 1);
+ if (hasData)
+ {
+ sb.Append(" type=").Append((int)renderType)
+ .Append(" post=").Append(renderPost ? 1 : 0)
+ .Append(" shadow=").Append(renderShadows ? 1 : 0)
+ .Append(" vmask=").Append(volumeMask.value)
+ .Append(" aa=").Append((int)aa)
+ .Append(" stack=").Append(stack == null ? 0 : stack.Length);
+ }
+ return sb.ToString();
+ }
+ }
+}
diff --git a/Assets/WL/PixelCamera/PixelCameraRig.cs.meta b/Assets/WL/PixelCamera/PixelCameraRig.cs.meta
new file mode 100644
index 000000000..25a41d403
--- /dev/null
+++ b/Assets/WL/PixelCamera/PixelCameraRig.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 861b4bf4226c29b438df6f1367a332b6
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/WL/PixelCamera/WLPixelCameraSettings.cs b/Assets/WL/PixelCamera/WLPixelCameraSettings.cs
new file mode 100644
index 000000000..90800bc31
--- /dev/null
+++ b/Assets/WL/PixelCamera/WLPixelCameraSettings.cs
@@ -0,0 +1,152 @@
+// ─────────────────────────────────────────────────────────────────────────────
+// WLPixelCameraSettings.cs — Critter 3D Pixel Camera 리그 값의 SOT (C45)
+//
+// PD 지시 #814(「도트 게임처럼」) · 발주서 WL-814b §1-3 (2026-09-10)
+//
+// 값의 SOT = Assets/WL/Combat/Settings/Resources/WL/WLPixelCameraSettings.asset
+// → Resources.Load("WL/WLPixelCameraSettings") 1회 로드 후 캐시(기존 WL 설정 SO 관례).
+//
+// 🔴 C8 — enabled = 0 (또는 RuntimeDisabled = true) 이면 리그가 아예 조립되지 않고,
+// 이미 조립돼 있으면 다음 틱에 원본 카메라 값이 100 % 복원된다(원본 동작과 동일).
+//
+// 🔴 원본 스크립트 0 · 원본 프리팹/씬 디스크 수정 0. 이 SO 와 PixelCameraRig.cs 만이 WL 신규 파일이다.
+// ─────────────────────────────────────────────────────────────────────────────
+
+using UnityEngine;
+
+namespace WL.PixelArt
+{
+ /// Followed 프록시를 어떻게 원본 카메라에 붙일지.
+ public enum PixelProxyMode
+ {
+ /// 원본 Main Camera 의 자식(localPos 0 · localRot identity). 지연 0 · 프레임당 비용 0 · GC 0. 권장.
+ ChildOfCamera = 0,
+ /// 독립 오브젝트 + 미러 스크립트([DefaultExecutionOrder(-100)] LateUpdate). 1프레임 지연.
+ MirrorScript = 1,
+ }
+
+ /// Critter 픽셀 카메라 리그 값. 전부 여기서만 바꾼다(코드 상수 0).
+ [CreateAssetMenu(fileName = "WLPixelCameraSettings", menuName = "WL/Pixel Camera Settings", order = 814)]
+ public sealed class WLPixelCameraSettings : ScriptableObject
+ {
+ public const string ResourcesPath = "WL/WLPixelCameraSettings";
+
+ static WLPixelCameraSettings s_cached;
+ static bool s_lookupDone;
+
+ /// Resources 에서 1회 로드 후 캐시. 없으면 null(= 기능 off).
+ public static WLPixelCameraSettings Instance
+ {
+ get
+ {
+ if (!s_lookupDone)
+ {
+ s_lookupDone = true;
+ s_cached = Resources.Load(ResourcesPath);
+ }
+ return s_cached;
+ }
+ }
+
+ /// 진단·A/B 전용 런타임 스위치(WLHitFeel.RuntimeDisabled 선례). 에셋을 안 건드리고 이 기능만 끈다.
+ public static bool RuntimeDisabled;
+
+ /// 이 기능이 살아 있는가(에셋 존재 + enabled + !RuntimeDisabled).
+ public static bool Enabled
+ {
+ get { var i = Instance; return i != null && i.enabled && !RuntimeDisabled; }
+ }
+
+ /// 테스트용: 캐시를 비워 다음 접근 때 다시 Resources.Load 한다.
+ public static void ClearCache() { s_cached = null; s_lookupDone = false; }
+
+ // ───────────────────────────────────────── 마스터
+ [Header("마스터 (C8)")]
+ [Tooltip("0 이면 리그를 만들지 않고, 이미 만들었으면 원본 카메라를 100 % 복원한다.")]
+ public bool enabled = true;
+
+ [Tooltip("1 이면 조립/복원 로그를 1줄씩 남긴다. LogError 는 쓰지 않는다(813z).")]
+ public bool verboseLog = false;
+
+ // ───────────────────────────────────────── 조립 경계
+ [Header("조립 경계 (811q EffectWarmup / 811o CameraFramingOverride 와 같은 판정)")]
+ [Tooltip("맵 진입 경계(메인 PC 교체 또는 맵 ID 변경)에서 자동 조립한다. 0 이면 프로브만 조립할 수 있다.")]
+ public bool assembleOnMapEnter = true;
+
+ [Tooltip("로비에서도 조립할지. 기본 0 = 인게임 맵에서만.")]
+ public bool assembleInLobby = false;
+
+ [Tooltip("경계 폴링 주기(초).")]
+ public float pollSeconds = 0.25f;
+
+ // ───────────────────────────────────────── 리그 원본
+ [Header("Critter 리그")]
+ [Tooltip("Assets/3DPixelCamera/URP/PixelCameraSystem.prefab (URP.unitypackage 해제로 생긴 프리팹).")]
+ public GameObject pixelCameraSystemPrefab;
+
+ [Tooltip("리그 전용 레이어 인덱스. 게임 카메라는 이 레이어를 빼고, 뷰 카메라는 이 레이어만 그린다. 프로젝트 미명명 레이어를 쓴다(TagManager 수정 0).")]
+ [Range(0, 31)] public int rigLayer = 31;
+
+ [Tooltip("프록시 방식. ChildOfCamera = 원본 카메라의 자식(지연 0 · 권장).")]
+ public PixelProxyMode proxyMode = PixelProxyMode.ChildOfCamera;
+
+ // ───────────────────────────────────────── 투영·해상도
+ [Header("직교 투영 · 픽셀 해상도")]
+ [Tooltip("원본 Main Camera 에 적용할 orthographicSize(= 화면 세로 절반의 월드 단위). "
+ + "기본 3.8 = 원근 fov 60 · 카메라 거리 6.58 m 의 반높이(tan30° × 6.58).")]
+ [Range(1f, 12f)] public float orthoSize = 3.8f;
+
+ [Tooltip("저해상도 RT 의 세로 픽셀 수(SetHeight). 가로는 화면 비율로 자동(9:16 · 480 → 270×480).")]
+ [Range(60, 1080)] public int pixelHeight = 480;
+
+ [Tooltip("Critter 뷰 카메라가 캔버스 가장자리를 넘지 않으려고 (1 − 2/pixelHeight) 만큼 줌아웃하는 것을 보정한다. "
+ + "1 이면 GameCameraZoom = orthoSize / (1 − 2/pixelHeight) 로 올려 화면 매핑을 orthoSize 와 정확히 맞춘다.")]
+ public bool compensateViewZoom = true;
+
+ // ───────────────────────────────────────── Critter 값
+ [Header("Critter PixelCameraManager 값")]
+ [Tooltip("픽셀 격자(voxel grid) 스냅. 정지 물체의 픽셀이 떨리지 않게 한다.")]
+ public bool voxelGridMovement = true;
+
+ [Tooltip("서브픽셀 보정. 격자 스냅의 뚝뚝 끊김을 뷰 카메라 오프셋으로 되돌린다.")]
+ public bool subpixelAdjustments = true;
+
+ [Tooltip("followed 트랜스폼의 회전도 따라간다.")]
+ public bool followRotation = true;
+
+ [Tooltip("Critter 가 게임 카메라의 orthographicSize 를 직접 제어한다.")]
+ public bool controlGameZoom = true;
+
+ [Tooltip("뷰 카메라 줌(−1~1). 1 = 캔버스를 화면에 꽉 채운다.")]
+ [Range(-1f, 1f)] public float viewCameraZoom = 1f;
+
+ [Tooltip("뷰 카메라를 원본 Main Camera 의 URP 카메라 스택에 Overlay 로 끼운다(권장). "
+ + "0 이면 Base 로 두고 depth 를 원본보다 1 높인다.")]
+ public bool viewCameraInMainStack = true;
+
+ // ───────────────────────────────────────── 회전 중 스냅 해제
+ [Header("회전 중 스냅 해제 (Critter 문서 권고)")]
+ [Tooltip("카메라가 빠르게 돌 때 격자 스냅·서브픽셀 보정을 잠시 끈다(811o 구도 전환 · 보스 연출).")]
+ public bool disableSnapWhileRotating = true;
+
+ [Tooltip("이 각속도(도/초)를 넘으면 회전 중으로 본다.")]
+ public float rotationSnapOffDegPerSec = 30f;
+
+ [Tooltip("회전이 멎고 이 시간(초)이 지나면 스냅을 다시 켠다.")]
+ public float rotationSnapResumeSeconds = 0.25f;
+
+ // ───────────────────────────────────────── 원본 카메라 처리
+ [Header("원본 Main Camera 처리 (MainCamera 태그·RealCamera·AudioListener 전부 유지)")]
+ [Tooltip("원본 카메라가 그릴 레이어. 기본 0 = 월드를 그리지 않는다(인게임 UI 캔버스는 UICamera Overlay 가 그린다).")]
+ public int mainCameraCullingMask = 0;
+
+ [Tooltip("원본 카메라의 포스트프로세싱을 끈다(픽셀 결과를 다시 후처리하지 않게). 게임 카메라 쪽에서 처리한다.")]
+ public bool mainCameraPostProcessingOff = true;
+
+ [Tooltip("원본 카메라의 포스트프로세싱 설정을 저해상도 게임 카메라로 복사한다(블룸 등이 픽셀 해상도로 들어간다).")]
+ public bool copyPostProcessingToGameCamera = true;
+
+ [Tooltip("원본 카메라의 배경을 단색 검정으로 바꾼다(스카이박스 클리어 비용 제거). 복원 시 원값으로 되돌린다.")]
+ public bool mainCameraSolidBlack = true;
+ }
+}
diff --git a/Assets/WL/PixelCamera/WLPixelCameraSettings.cs.meta b/Assets/WL/PixelCamera/WLPixelCameraSettings.cs.meta
new file mode 100644
index 000000000..ec8533971
--- /dev/null
+++ b/Assets/WL/PixelCamera/WLPixelCameraSettings.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: aedb96845e568d44889723065b993c14
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant: