using UnityEngine; /// /// 根据屏幕宽高比,对 gameplay 相机做分辨率适配,让宽屏下轨道观感更接近设计(16:9)。 /// /// 需求(用户指定):越宽的屏幕(21:9/32:9)轨道越缩在中间、显细,左右与 UI 空出大黑缝。 /// 解决方案:宽屏时把相机从设计基准(z=-8, X=-40°)逐步插值到"z 更高 + X 更朝水平"的目标位姿, /// 让轨道透视放大、铺满视野,同时保持判定线距离/视距/业务逻辑不变(音符/判定用世界坐标,不受相机缩放影响)。 /// /// 操作对象:**直接改相机本体(Main Camera 子物体)自身的 local z 高度与 local X 旋转**, /// 不动其父/祖父 pivot(drift/skill pivot)。通过 effectEventController.SetResolutionCameraSelf 施加, /// 由该方法处理与 SmoothShake(写相机 local)、冲刺(写相机 local z)的共享——空闲时写入持久生效, /// 抖动/冲刺触发时会以当前 local 重新捕获基准。不碰任何 UI:UI 贴边逻辑独立,本脚本只改相机位姿。 /// /// 用一个 bool(enableTuning)开关。关闭时恢复设计基准(与未加此脚本逐像素一致)。 /// 16:9 及更窄(平板 1.6、竖屏)保持设计基准不动;宽屏线性插值;21:9 及更宽夹在最大偏移(用户指定的上限)。 /// [DisallowMultipleComponent] public sealed class CameraResolutionTuner : MonoBehaviour { [Tooltip("是否启用按分辨率微调相机。关闭则恢复设计基准。")] public bool enableTuning = true; [Tooltip("设计基准宽高比。16:9 = 1.7778。此比例及更窄时无微调。")] public float designAspect = 16f / 9f; [Tooltip("最大偏移的宽高比上限。21:9 = 2.3333。达到或超过此比例时夹在最大偏移。")] public float maxOffsetAspect = 21f / 9f; [Header("21:9 时相机本体(Main Camera)的目标 local 位姿(最大偏移)")] [Tooltip("21:9 时相机本体的目标 local Z 高度。用户指定 2.5(相机自身 z=2.5)。")] public float targetCameraY = -2.13f; public float targetCameraZ = 3.6f; [Tooltip("21:9 时相机本体的目标 local X 旋转角度。用户指定 5(相机自身 X=5°)。")] public float targetCameraRotX = -10f; private float _lastAspect = -1f; private bool _lastEnabled; private bool _applied; // 上次 Apply 是否成功写入相机(相机/单例未就绪时为 false,下一帧重试) private void OnEnable() { _lastAspect = -1f; _applied = false; Apply(); } private void Update() { float aspect = (float)Screen.width / Mathf.Max(1, Screen.height); // 宽高比/开关变化,或此前尚未成功写入(相机/单例未就绪),则重试。 if (!_applied || Mathf.Abs(aspect - _lastAspect) > 0.0001f || enableTuning != _lastEnabled) { Apply(); } } private void Apply() { var eff = effectEventController.Instance; if (eff == null) { _applied = false; return; } float aspect = (float)Screen.width / Mathf.Max(1, Screen.height); _lastAspect = aspect; _lastEnabled = enableTuning; if (!enableTuning) { // 关闭:t=0 → 相机本体回到 local 设计基准(运行时为 0/identity)。 _applied = eff.SetResolutionCameraSelf(0f, targetCameraRotX, targetCameraZ, targetCameraY); return; } // 16:9 及更窄:t=0(无微调,与设计逐像素一致)。 // 16:9 ~ 21:9:线性插值 t ∈ [0,1]。 // 21:9 及更宽:t=1(夹在最大偏移上限)。 float t = 0f; if (aspect > designAspect) { if (aspect >= maxOffsetAspect) { t = 1f; // 超宽屏:夹在最大偏移 } else { // 插值区间:designAspect(16:9≈1.778) → maxOffsetAspect(21:9≈2.333) t = (aspect - designAspect) / Mathf.Max(0.0001f, maxOffsetAspect - designAspect); t = Mathf.Clamp01(t); } } // aspect <= designAspect:t=0(无微调)。 _applied = eff.SetResolutionCameraSelf(t, targetCameraRotX, targetCameraZ, targetCameraY); } }