Files
Vision/Assets/Scripts/UI/CameraDistanceByOrientation.cs
2026-10-14 19:33:29 +08:00

70 lines
3.1 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 Cinemachine;
using UnityEngine;
/// <summary>
/// 按屏幕方向切换虚拟相机的跟随距离。
///
/// 挂在 Canvas 或任意「拉伸铺满」的 UI 节点上(这类节点的尺寸会随屏幕变化,Unity 才会回调),
/// 再把要改的虚拟相机拖到 virtualCamera 字段。该虚拟相机的 Body 必须是 Framing Transposer
/// (Camera Distance 是 Body 上的字段,不在虚拟相机组件本身)。
///
/// 触发时机:Unity 只在 RectTransform 尺寸变化时调用 OnRectTransformDimensionsChange,
/// 所以这里没有 Update、不轮询、初始化时不写值;只有屏幕方向真的翻转那一次才写一次距离。
/// (尺寸变了但方向没变——比如布局调整——也不会写。)
/// </summary>
[DisallowMultipleComponent]
public class CameraDistanceByOrientation : MonoBehaviour
{
[Header("引用(必须在 Inspector / 预制体里指定)")]
[Tooltip("要改跟随距离的虚拟相机;它的 Body 必须是 Framing Transposer")]
[SerializeField] private CinemachineVirtualCamera virtualCamera;
[Header("相机距离")]
[Tooltip("横屏时的 Camera Distance")]
[SerializeField] private float landscapeDistance = 13f;
[Tooltip("竖屏时的 Camera Distance")]
[SerializeField] private float portraitDistance = 30f;
private CinemachineFramingTransposer _framingTransposer;
private bool _isPortrait;
private void Awake()
{
if (GetComponent<RectTransform>() == null)
Debug.LogError("[CameraDistanceByOrientation] 这个物体没有 RectTransform,收不到尺寸变化回调;" +
"请挂到 Canvas 或任意拉伸铺满的 UI 节点上。", this);
if (virtualCamera == null)
{
Debug.LogError("[CameraDistanceByOrientation] 没有指定 virtualCamera,请在 Inspector 里拖入。", this);
return;
}
_framingTransposer = virtualCamera.GetCinemachineComponent<CinemachineFramingTransposer>();
if (_framingTransposer == null)
Debug.LogError("[CameraDistanceByOrientation] 虚拟相机的 Body 不是 Framing Transposer,改不了 Camera Distance。", this);
// 只记下开局方向,不写相机
_isPortrait = IsPortrait();
}
/// <summary>RectTransform 尺寸变化时由 Unity 调用(屏幕旋转、分辨率变化都会触发)。</summary>
private void OnRectTransformDimensionsChange()
{
bool portrait = IsPortrait();
if (portrait == _isPortrait)
return; // 尺寸变了但方向没变,不动相机
_isPortrait = portrait; // 只在翻转的这一次写值
if (_framingTransposer == null)
return; // Awake 已经报过错
_framingTransposer.m_CameraDistance = portrait ? portraitDistance : landscapeDistance;
}
/// <summary>屏幕高度大于宽度算竖屏。编辑器里拖动 Game 视图尺寸也能触发,方便验证。</summary>
private static bool IsPortrait() => Screen.height > Screen.width;
}