Files
2026-07-26 03:44:27 +08:00

98 lines
4.2 KiB
C#
Raw Permalink 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.
using UnityEngine;
/// <summary>
/// 根据屏幕宽高比,对 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 及更宽夹在最大偏移(用户指定的上限)。
/// </summary>
[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 <= designAspectt=0(无微调)。
_applied = eff.SetResolutionCameraSelf(t, targetCameraRotX, targetCameraZ, targetCameraY);
}
}