Unity MyFramework 用法说明(二十九):使用 CameraManager 统一管理游戏摄像机

项目中往往同时存在主场景摄像机、UI 摄像机、角色预览摄像机和 RenderTexture 摄像机。如果各系统直接操作 Unity Camera,主摄像机切换、URP Camera Stack、AudioListener 和跟随逻辑就会散落到不同代码中。

MyFramework 使用 CameraManager 统一管理摄像机,并通过 GameCamera 为 Unity Camera 增加组件化能力。

项目地址:

github.com/ZHOURUIH/My...

一、框架默认摄像机

CameraManager.init() 会创建:

bash 复制代码
MainCamera    默认主摄像机
UICamera      UGUI 摄像机
BlurCamera    UI 背景模糊摄像机

常用接口:

bash 复制代码
GameCamera mainCamera =
	mCameraManager.getMainCamera();

GameCamera uiCamera =
	mCameraManager.getUICamera();

GameCamera blurCamera =
	mCameraManager.getUIBlurCamera();

业务代码应通过 GameCamera 操作摄像机,而不是反复查找 Unity Camera

二、创建并切换主摄像机

场景中存在 BattleCamera 节点时,可以直接创建包装对象:

bash 复制代码
public class BattleCameraSystem : FrameSystem
{
	protected GameCamera mBattleCamera;

	public override void init()
	{
		base.init();

		mBattleCamera =
			mCameraManager.createCamera(
				"BattleCamera");

		mCameraManager.setMainCamera(
			mBattleCamera);
	}

	public override void destroy()
	{
		mCameraManager
			.resetToDefaultMainCamera();

		mCameraManager.destroyCamera(
			mBattleCamera);

		mBattleCamera = null;
		base.destroy();
	}
}

setMainCamera() 会停用旧主摄像机,再激活新摄像机。销毁当前主摄像机后,框架会尝试恢复默认摄像机,避免没有可用主摄像机。

三、GameCamera 提供的能力

GameCamera 继承自 MovableObject,除了位置和旋转,还封装了:

bash 复制代码
FOV 与正交尺寸
渲染层和 Camera Depth
屏幕坐标转世界坐标
RenderTexture
URP Camera Stack
后处理开关
目标跟随组件

例如屏幕坐标转换:

bash 复制代码
Vector3 worldPos =
	mCameraManager.getMainCamera()
		.screenToWorld(screenPos, false);

设置正交大小:

bash 复制代码
mBattleCamera.setOrthoSize(540.0f);

设置可见层:

bash 复制代码
mBattleCamera.setVisibleLayer(layerMask);

四、让摄像机跟随角色

GameCamera 内置了多种连接器:

bash 复制代码
CameraLinkerThirdPerson
CameraLinkerSmoothFollow
CameraLinkerFirstPerson
CameraLinkerFree
CameraLinkerSmoothRotate

例如平滑跟随玩家:

bash 复制代码
CameraLinkerSmoothFollow linker =
	mBattleCamera.linkTarget(
		typeof(CameraLinkerSmoothFollow),
		player) as CameraLinkerSmoothFollow;

linker.setRelativePosition(
	new Vector3(0.0f, 6.0f, -8.0f));

linker.setLookAtOffset(
	new Vector3(0.0f, 1.5f, 0.0f));

linker.setLookAtTarget(true);
linker.setNormalSpeed(5.0f);
linker.applyRelativePosition(
	linker.getRelativePosition());

连接器默认在 LateUpdate 中更新,可以减少目标移动后摄像机延迟跟随产生的抖动。

停止跟随:

bash 复制代码
mBattleCamera.unlinkTarget();

五、平滑修改 FOV

FOV 变化接入了关键帧系统:

bash 复制代码
CmdGameCameraFOV.execute(
	mBattleCamera,
	0.25f,
	0.0f,
	mBattleCamera.getFOVY(),
	40.0f,
	KEY_CURVE.QUAD_OUT);

可以用于冲刺扩大视野、瞄准缩小视野和剧情镜头拉近。

正交摄像机则可以使用 CmdGameCameraOrthoSize 平滑改变显示范围。

六、URP Camera Stack

启用 URP 时,createCamera() 会读取摄像机的 RenderType

如果创建的是 Overlay 摄像机,框架会按照 overlayCameraDepth 排序,并默认加入主摄像机的 Camera Stack:

bash 复制代码
GameCamera sceneUICamera =
	mCameraManager.createCamera(
		sceneUICameraObject,
		10);

Base 与 Overlay 摄像机必须位于同一个 Unity Scene。

用于 RenderTexture 的摄像机通常不需要 UI Stack,创建时应关闭自动添加:

bash 复制代码
GameCamera previewCamera =
	mCameraManager.createCamera(
		previewCameraObject,
		0,
		true,
		false);

七、AudioListener 自动管理

Unity 场景中只能有一个启用的 AudioListener

CameraManager 按以下顺序选择:

bash 复制代码
当前主摄像机
    ↓
UI 摄像机
    ↓
第一个激活的摄像机

切换摄像机时,业务层不需要逐个修改 AudioListener

八、总结

CameraManager 负责摄像机的创建、销毁、主摄像机切换、URP Stack 和 AudioListener。

GameCamera 负责摄像机参数、坐标转换、目标跟随、关键帧变化和 RenderTexture。

这样场景切换、角色跟随、UI 叠加和镜头演出都能使用同一套生命周期,不需要让每个系统直接操作 Unity Camera

相关推荐
SmalBox9 小时前
【节点】[Or节点]原理解析与实际应用
unity3d·游戏开发·图形学
_zhourui_h_1 天前
Unity MyFramework 用法说明(二十七):使用 InputSystem 与 KeyMappingSystem 统一管理输入和快捷键
unity3d
_ZHOURUI_H_1 天前
Unity MyFramework 用法说明(二十五):使用 AtlasManager 统一管理图集与 Sprite 引用
ui·unity·游戏引擎·unity3d·游戏开发
_zhourui_h_1 天前
Unity MyFramework 用法说明(二十六):使用 RedPointSystem 构建树形红点逻辑
unity3d
SmalBox1 天前
【节点】[Not节点]原理解析与实际应用
unity3d·游戏开发·图形学
万亿少女的梦1682 天前
基于Unity3D的双状态场景解密游戏设计与实现
unity3d·游戏开发·场景渲染·交互系统·叙事设计
SmalBox2 天前
【节点】[Nand节点]原理解析与实际应用
unity3d·游戏开发·图形学
SmalBox3 天前
【节点】[IsNaN节点]原理解析与实际应用
unity3d·游戏开发·图形学
SmalBox4 天前
【节点】[IsInfinite节点]原理解析与实际应用
unity3d·游戏开发·图形学