总览
这三个名字很像,新手最容易混。记住一句话:Camera Asset 是完整相机方案入口,Camera Rig 是可复用镜头预制,Camera Node 是节点树里的一个运算步骤。
架构分析
UCameraAsset 持有 UCameraDirector、共享 Enter/Exit Transitions、默认参数、参数定义和 AllocationInfo。你把它挂到 UGameplayCameraComponent 上,运行时就从这里找到 Director。
UCameraRigAsset 继承 UBaseCameraObject,核心属性是 RootNode。它还持有 GameplayTags、进入/退出 Transition 和 ECameraRigInitialOrientation。一个项目通常会有很多 Rig:Follow、Aim、LockOn、Dialogue、Vehicle、Death、Spectator。
UCameraNode 是抽象基类。它有 GetChildren、PreBuild、Build、BuildEvaluator,真正每帧执行的是对应的 FCameraNodeEvaluator。也就是说,资产里的 UObject 节点负责配置,运行时 Evaluator 负责算。
常用 Node 选择
| 节点类型 | 用途 | 项目里怎么用 |
|---|---|---|
| AttachToPlayerPawn / AttachToActor | 确定跟随对象 | 第三人称、载具、对话目标 |
| BoomArm | 绕支点旋转和拉臂 | 替代一部分 SpringArm 行为 |
| DampenPosition / DampenRotation | 平滑移动和旋转 | 角色急停、镜头延迟 |
| CollisionPush | 防止穿墙 | 第三人称必备 |
| FieldOfView / Filmback / Lens | 镜头参数 | 冲刺、瞄准、电影感 |
| InputAxisBinding2D / AutoRotate | 输入和自动回正 | 右摇杆、鼠标、手柄 |
| CameraRigCameraNode | 嵌套 Rig | 复用通用子镜头 |
自定义节点骨架
自定义节点适合处理项目特有逻辑,例如“锁定目标时根据敌人高度微调肩位”。不要把能用参数解决的东西都写成节点。
#include "Core/CameraNode.h"
#include "Core/CameraNodeEvaluator.h"
UCLASS(meta=(CameraNodeCategories="Project,Transform"))
class ULockOnShoulderOffsetCameraNode : public UCameraNode
{
GENERATED_BODY()
public:
UPROPERTY(EditAnywhere, Category="LockOn")
FVector3dCameraParameter ShoulderOffset = FVector(0.0, 60.0, 20.0);
protected:
virtual FCameraNodeEvaluatorPtr OnBuildEvaluator(FCameraNodeEvaluatorBuilder& Builder) const override;
};
class FLockOnShoulderOffsetEvaluator : public UE::Cameras::FCameraNodeEvaluator
{
UE_DECLARE_CAMERA_NODE_EVALUATOR(GAMEPLAYCAMERAS_API, FLockOnShoulderOffsetEvaluator)
protected:
virtual void OnRun(const FCameraNodeEvaluationParams& Params, FCameraNodeEvaluationResult& OutResult) override
{
const FVector Current = OutResult.CameraPose.GetLocation();
OutResult.CameraPose.SetLocation(Current + FVector(0.0, 60.0, 20.0));
}
};
上面只是骨架。真实项目里你会用 TCameraParameterReader 读取参数、在 OnBuild 注册需要的变量或上下文数据,并在 DebugBlock 里输出当前偏移值。
使用案例
如果你要做“右肩/左肩切换”,优先把肩位做成 FVector3dCameraParameter,由参数覆盖或变量驱动;如果你要做“目标太高时镜头自动抬一点,并且要参与调试”,再考虑自定义 Node。判断标准是:它是否需要访问运行时上下文、是否在多个 Rig 中复用、是否需要 Debug 输出。
项目落地
先用内置节点搭出 80% 行为。只有当你发现同一类逻辑在多个 Rig 里重复,并且需要访问项目数据时,才写自定义节点。资产层面保持 Rig 小而清楚:Follow Rig 管跟随,Aim Rig 管瞄准,Dialogue Rig 管对话构图,不要在一个 Rig 里用一堆开关模拟所有状态。
常见坑
- 把 Camera Asset 当成 Rig:Asset 是入口,Rig 才是节点树。
- 忽略 Build:Rig/Asset 会生成运行时分配信息和参数定义,Dirty 状态要处理。
- 自定义节点里直接找世界对象:优先通过 EvaluationContext、变量或 Context Data 传入。
- 一个节点既改 Location 又管输入又管碰撞:职责太大,后期无法调试。
源码依据
UCameraAsset 的 BuildCamera 会构建并验证所有 Camera Rig;UCameraRigAsset 的 RootNode 是节点树入口;UCameraNode 的 OnBuildEvaluator 产生运行时 Evaluator;FCameraNodeEvaluationResult 里包含可修改的 CameraPose、VariableTable、ContextDataTable 和 PostProcess。
源码路径索引
GameplayCameras/Public/Core/CameraAsset.hGameplayCameras/Public/Core/CameraRigAsset.hGameplayCameras/Public/Core/CameraNode.hGameplayCameras/Public/Core/CameraNodeEvaluator.h