Files
zeling_v2/Assets/_Game/Scripts/Camera/CameraArea.cs

91 lines
4.7 KiB
C#
Raw 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;
using Unity.Cinemachine;
namespace BaseGames.Camera
{
/// <summary>
/// 相机区域数据组件。一个房间场景内可放置任意数量的 CameraArea
/// 每个区域独立定义限位范围、可视边界与混合配置。
///
/// 运行时由 <see cref="CameraStateController"/> 管理:
/// - <c>_dedicatedCamera</c> 为空 → 使用 Persistent 场景中的两台全局 VCam 交替承接,
/// 减少场景内 VCam 数量,相机参数统一由全局 VCam 配置。
/// - <c>_dedicatedCamera</c> 不为空 → 激活该专有 VCam优先级高于全局 VCam
/// 适用于需要独特相机参数FOV / Offset / 阻尼)的特殊区域。
/// </summary>
public class CameraArea : MonoBehaviour
{
[Header("限位区域")]
[Tooltip("定义相机移动边界的 PolygonCollider2D通常挂载在子节点 AreaBoundary 上)。\n" +
"会被赋给全局 VCam 的 CinemachineConfiner2D.BoundingShape2D。")]
[SerializeField] private PolygonCollider2D _confinerCollider;
[Header("可视区域(透视相机)")]
[Tooltip("摄像机应显示的最大可视矩形(世界坐标)。\n" +
"Scene 视图中可直接拖拽四条边编辑,然后点击 Inspector 中的\n" +
"「从可视区域更新限位区域(透视)」按钮将其换算为限位多边形。")]
[SerializeField] private Rect _visibleBounds = new Rect(-12f, -6f, 24f, 12f);
[Tooltip("摄像机到场景平面Z = 0的垂直距离用于透视视口尺寸计算。\n" +
"留 0 时自动取 transform.position.z 的绝对值(推荐)。")]
[SerializeField] private float _cameraDepth = 0f;
[Header("混合配置")]
[SerializeField] private CameraBlendProfileSO _blendProfile;
[Header("专有虚拟相机(可选)")]
[Tooltip("为空时由全局双 VCam 交替过渡(推荐,节省 VCam 数量)。\n" +
"不为空时激活此专有 CinemachineCamera优先级高于全局 VCam。\n" +
"适用于需要独特 FOV / Noise / LookAt 等参数的特殊区域。")]
[SerializeField] private CinemachineCamera _dedicatedCamera;
[Tooltip("专有 VCam 激活时使用的优先级,须高于全局 VCam 的 _globalActivePriority默认 10。")]
[SerializeField] private int _dedicatedPriority = 20;
// ── 公开属性 ──────────────────────────────────────────────────────────
public PolygonCollider2D ConfinerCollider => _confinerCollider;
public CameraBlendProfileSO BlendProfile => _blendProfile;
public Rect VisibleBounds => _visibleBounds;
public bool HasDedicated => _dedicatedCamera != null;
public CinemachineCamera DedicatedCamera => _dedicatedCamera;
public int DedicatedPriority => _dedicatedPriority;
/// <summary>
/// 摄像机到场景平面的有效深度(用于透视视口换算)。
/// _cameraDepth &gt; 0 时使用配置值,否则自动读取 |transform.position.z|,再兜底 10。
/// </summary>
public float CameraDepth
{
get
{
if (_cameraDepth > 0f) return _cameraDepth;
float z = Mathf.Abs(transform.position.z);
return z > 0.01f ? z : 10f;
}
}
// ── Gizmo ────────────────────────────────────────────────────────────
private void OnDrawGizmosSelected()
{
// 黄色:可视区域
Vector3 center = new Vector3(_visibleBounds.center.x, _visibleBounds.center.y, 0f);
Vector3 size = new Vector3(_visibleBounds.width, _visibleBounds.height, 0.01f);
Gizmos.color = new Color(1f, 0.85f, 0.15f, 0.10f);
Gizmos.DrawCube(center, size);
Gizmos.color = new Color(1f, 0.85f, 0.15f, 0.90f);
Gizmos.DrawWireCube(center, size);
// 青色:专有 VCam 指示线
if (_dedicatedCamera != null)
{
Gizmos.color = new Color(0.2f, 1f, 0.8f, 0.8f);
Gizmos.DrawLine(transform.position,
_dedicatedCamera.transform.position);
}
}
}
}