Files
2026-07-24 04:43:13 +08:00

121 lines
4.4 KiB
C#

using UnityEngine;
/// <summary>
/// 按屏幕宽高比动态拉长轨道视觉物体(track1-5)的 Y 缩放,让宽屏下轨道更饱满。
///
/// 原理:宽屏时水平视野大、轨道相对缩在中间显细。降相机高度+抬头能让轨道透视放大,
/// 但仍不够饱满。再叠加"拉长轨道 Y 缩放"填满纵向视野,视觉更满。
///
/// 关键:轨道只是背景视觉,判定是几何驱动(音符世界 Y vs 判定线世界 Y)。
/// 缩放轨道 localScale 不影响音符生成/下落/判定——它们全用世界坐标,与轨道视觉无关。
///
/// 用法:挂到场景任意物体(会自动找 track1-5 或指定 trackParent)。运行时自动扫描并缩放。
/// </summary>
[DisallowMultipleComponent]
public sealed class TrackScaler : MonoBehaviour
{
[Tooltip("是否启用轨道缩放。关闭则恢复基准值 2.5。")]
public bool enableScaling = true;
[Tooltip("设计基准宽高比。16:9 = 1.7778。此比例下缩放为基准值。")]
public float designAspect = 16f / 9f;
[Tooltip("轨道 Y 缩放的基准值(场景序列化的初始值)。从这个值开始按宽高比放大。")]
public float baseScaleY = 2.5f;
[Header("宽屏(aspect > 设计)缩放")]
[Tooltip("每偏离设计宽高比 1.0,额外叠加的 Y 缩放倍数。宽屏拉长轨道让视觉更满。")]
public float widePerAspectScaleY = 0.8f;
[Tooltip("Y 缩放的绝对上限。避免极端超宽屏拉得过长。")]
public float maxScaleY = 4.5f;
[Tooltip("(可选)轨道的父节点。留空则自动全场景查找 track1-5。")]
public Transform trackParent;
private Transform[] _tracks;
private float _lastAspect = -1f;
private bool _lastEnabled;
private void OnEnable()
{
FindTracks();
_lastAspect = -1f;
Apply();
}
private void Update()
{
float aspect = (float)Screen.width / Mathf.Max(1, Screen.height);
if (Mathf.Abs(aspect - _lastAspect) > 0.0001f || enableScaling != _lastEnabled)
{
Apply();
}
}
private void FindTracks()
{
if (trackParent != null)
{
// 从指定父节点下找
_tracks = new Transform[5];
for (int i = 0; i < trackParent.childCount; i++)
{
Transform child = trackParent.GetChild(i);
if (child.name == "track1") _tracks[0] = child;
else if (child.name == "track2") _tracks[1] = child;
else if (child.name == "track3") _tracks[2] = child;
else if (child.name == "track4") _tracks[3] = child;
else if (child.name == "track5") _tracks[4] = child;
}
}
else
{
// 全场景查找(慢,但兜底)
_tracks = new Transform[5];
GameObject go1 = GameObject.Find("track1");
GameObject go2 = GameObject.Find("track2");
GameObject go3 = GameObject.Find("track3");
GameObject go4 = GameObject.Find("track4");
GameObject go5 = GameObject.Find("track5");
if (go1 != null) _tracks[0] = go1.transform;
if (go2 != null) _tracks[1] = go2.transform;
if (go3 != null) _tracks[2] = go3.transform;
if (go4 != null) _tracks[3] = go4.transform;
if (go5 != null) _tracks[4] = go5.transform;
}
}
private void Apply()
{
if (_tracks == null || _tracks.Length == 0)
{
FindTracks(); // 重试
if (_tracks == null || _tracks.Length == 0) return;
}
float aspect = (float)Screen.width / Mathf.Max(1, Screen.height);
_lastAspect = aspect;
_lastEnabled = enableScaling;
float targetScaleY = baseScaleY;
if (enableScaling && aspect > designAspect)
{
// 宽屏:额外拉长 Y
float dev = aspect - designAspect;
float extra = widePerAspectScaleY * dev;
targetScaleY = Mathf.Min(baseScaleY + extra, maxScaleY);
}
// aspect <= designAspect 或关闭:保持基准值
// 应用到所有轨道
for (int i = 0; i < _tracks.Length; i++)
{
if (_tracks[i] == null) continue;
Vector3 scale = _tracks[i].localScale;
scale.y = targetScaleY;
_tracks[i].localScale = scale;
}
}
}