91 lines
4.7 KiB
C#
91 lines
4.7 KiB
C#
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 > 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);
|
||
}
|
||
}
|
||
}
|
||
}
|