Project_WL/Assets/WL/PixelCamera/WLPixelCameraSettings.cs

153 lines
9.0 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// ─────────────────────────────────────────────────────────────────────────────
// 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<WLPixelCameraSettings>("WL/WLPixelCameraSettings") 1회 로드 후 캐시(기존 WL 설정 SO 관례).
//
// 🔴 C8 — enabled = 0 (또는 RuntimeDisabled = true) 이면 리그가 아예 조립되지 않고,
// 이미 조립돼 있으면 다음 틱에 원본 카메라 값이 100 % 복원된다(원본 동작과 동일).
//
// 🔴 원본 스크립트 0 · 원본 프리팹/씬 디스크 수정 0. 이 SO 와 PixelCameraRig.cs 만이 WL 신규 파일이다.
// ─────────────────────────────────────────────────────────────────────────────
using UnityEngine;
namespace WL.PixelArt
{
/// <summary>Followed 프록시를 어떻게 원본 카메라에 붙일지.</summary>
public enum PixelProxyMode
{
/// <summary>원본 Main Camera 의 자식(localPos 0 · localRot identity). 지연 0 · 프레임당 비용 0 · GC 0. 권장.</summary>
ChildOfCamera = 0,
/// <summary>독립 오브젝트 + 미러 스크립트([DefaultExecutionOrder(-100)] LateUpdate). 1프레임 지연.</summary>
MirrorScript = 1,
}
/// <summary>Critter 픽셀 카메라 리그 값. 전부 여기서만 바꾼다(코드 상수 0).</summary>
[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;
/// <summary>Resources 에서 1회 로드 후 캐시. 없으면 null(= 기능 off).</summary>
public static WLPixelCameraSettings Instance
{
get
{
if (!s_lookupDone)
{
s_lookupDone = true;
s_cached = Resources.Load<WLPixelCameraSettings>(ResourcesPath);
}
return s_cached;
}
}
/// <summary>진단·A/B 전용 런타임 스위치(WLHitFeel.RuntimeDisabled 선례). 에셋을 안 건드리고 이 기능만 끈다.</summary>
public static bool RuntimeDisabled;
/// <summary>이 기능이 살아 있는가(에셋 존재 + enabled + !RuntimeDisabled).</summary>
public static bool Enabled
{
get { var i = Instance; return i != null && i.enabled && !RuntimeDisabled; }
}
/// <summary>테스트용: 캐시를 비워 다음 접근 때 다시 Resources.Load 한다.</summary>
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;
}
}