70 lines
3.1 KiB
C#
70 lines
3.1 KiB
C#
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;
|
||
}
|