[AI教做人]CinemachineCamera 各项调整配置参数入门 + Profiler

AI建议用3.0

1. 反射缓存(最常见)

CinemachineBrain 内部大量用反射查找组件,每次 LateUpdate 都在做:

复制代码
// Cinemachine 内部简化
foreach (var vcam in allVirtualCameras)
{
    var components = vcam.GetComponents<Component>();  // ← 每帧调,有 GC
    foreach (var c in components)
    {
        var type = c.GetType();                       // ← 反射
        var method = type.GetMethod("ProcessCamera"); // ← 反射
        method.Invoke(c, null);                       // ← 装箱 GC
    }
}

2. 临时变量和协程

复制代码
// Cinemachine 内部 LateUpdate 里创建大量临时变量
void LateUpdate()
{
    var cameraPos = new Vector3();        // ← struct
    var lookAtPos = new Vector3();        // ← struct
    var damping = new List<float>();      // ← 每帧 new List
    var rotations = new Quaternion[3];    // ← 每帧 new Array
    // ...
}

Profiler 中表现

复制代码
CinemachineBrain.LateUpdate
  ├─ GetComponents<CinemachineVirtualCameraBase>()  2.1KB  GC
  ├─ List<VirtualCamera>.Add()                      0.8KB  GC
  ├─ CalculateLookAtDampingStyles()                 0.5KB  GC
  └─ UpdateVirtualCameras()
       └─ BlendRoot.Create()                        0.3KB  GC
   ------
  GC Alloc: 3-5KB/frame  Time: 0.5-1ms

解决方案

最直接:升级 Cinemachine

旧版 Cinemachine (2.x) GC 问题严重。Cinemachine 3.x 重写了内部架构,缓存了反射

复制代码
# package.json
"com.unity.cinemachine": "3.0.0"  ← 2.x 升 3.x

GC 从每帧 3-5KB 降到几乎 0。

如果不能升级:减少 vcam 数量
复制代码
// 不用的 vcam 必须禁用
vcam.Priority = 0;   // 不够,Priority=0 仍然会被 Brain 遍历
vcam.enabled = false; // 必须 enabled = false

Brain 遍历所有启用的 vcam,数量越少 GC 越少。

除了Camera 可能还有Cloth 的问题

留个尾巴

Packagemanager 安装

  1. Package Manager 安装 Cinemachine(如果是新版用 Cinemachine 3.x)
  2. Hierarchy 右键 → Cinemachine → Virtual Camera ,会自动生成一个 CM vcam1Main Camera 上的 CinemachineBrain
  3. 选中 CM vcam1,Inspector 里:
    • Follow → 拖入玩家 GameObject
    • LookAt → 拖入玩家 GameObject
  4. 选 Body 的绑定模式(推荐 Framing Transposer + Screen Space
  5. 运行,摄像机跟随

总共 3 步:装包 → 建 vcam → 拖 Follow/LookAt。

Visual Camera配置参数(按以下结构)

项目用的是 CinemachineVirtualCamera + CinemachinePOV,Follow/LookAt 分离。适合 ARPG 的合理配置如下:

场景结构

直接绑定骨骼为什么不好?骨骼点已经很多拉,一个腰部,一个头部,正好不是?

但其实还是创建独立结构比较好,原因不说了

复制代码
Player (角色)
├── vcamFollow  (空物体,放在角色胸口高度)
└── vcamLookAt  (空物体,放在角色头部稍上方)

vcam 推荐配置

Lens:

  • Field of View: 40-50(ARPG 不用太广,40 偏电影感,50 偏常规)

Body → Framing Transposer:

  • Tracked Object Offset: (0, 1.5, 0) (跟随点抬高到胸口)
  • Camera Distance: 5-6
  • Dead Zone Width: 0.15(角色在中间 15% 范围内移动不触发摄像机位移)
  • Dead Zone Height: 0.2
  • X Damping: 1.5
  • Y Damping: 1.5
  • Z Damping: 0.5(Z 跟快一点,避免拉近拉远延迟)

Aim → POV:

  • Vertical Axis → Value: -15(俯视 15 度,ARPG 标准俯角)
  • Vertical Axis → Range: Min -40 , Max 10
  • Horizontal Axis → Range: Min -60 , Max 60
  • H Recenter Target: Target(松开摇杆后回正)
  • H Recenter Speed: 3
  • V Recenter Target: Target
  • V Recenter Speed: 3

CinemachineInputProvider:

  • Horizontal Axis → Input Axis Name: Mouse X
  • Vertical Axis → Input Axis Name: Mouse Y

快速手动步骤

  1. 建 2 个空物体 vcamFollow / vcamLookAt,放在角色身上,高度分别约 1.2 / 1.6
  2. 建 vcam,Follow 拖 vcamFollow,LookAt 拖 vcamLookAt
  3. Body 选 Framing Transposer,按上面配
  4. Aim 选 POV,按上面配
  5. CinemachineInputProvider 组件,绑鼠标轴

这套配置的效果:摄像机在角色后上方 5-6 米,俯视 15 度,鼠标控制水平/垂直旋转,松手回正。

问题1Update()事件内的代码

  • 这行代码在每帧都将 lookAtVector 重置为 (0, lookAtHeight, 0)

  • 然后立即在 LookAt 中使用它

  • 这完全没必要,因为:

    • 如果 lookAtHeight 是常数,应该在Start/Awake中初始化一次

    • 如果 lookAtHeight 需要变化,应该单独控制,而不是每帧重置

最终修改代码:

cs 复制代码
private Vector3 lookAtVector;

//修改为 

private Vector3 lookAtVector => new Vector3(0,lookAtHeight,0);

问题2:Time.fixedDeltaTime 使用不当

csharp

cs 复制代码
currentHeight = Mathf.Lerp(currentHeight, wantedHeight, heightDamping * Time.fixedDeltaTime);
  • LateUpdate 中使用 Time.fixedDeltaTime 而不是 Time.deltaTime

  • LateUpdate 每帧调用,应该使用 Time.deltaTime

  • Time.fixedDeltaTime 用于FixedUpdate中的物理计算

应该改为:

csharp

cs 复制代码
currentHeight = Mathf.Lerp(currentHeight, wantedHeight, heightDamping * Time.deltaTime);

问题3:Mathf.SmoothDampAngle 用于距离计算

csharpCode

复制代码
usedDistance = Mathf.SmoothDampAngle(usedDistance, distance, ref zVelocity, 0.1f);
  • SmoothDampAngle 是专门处理角度(处理360°环绕)的

  • 用于距离计算可能不合适,应该用 Mathf.SmoothDamp

应该改为:

csharpCode

复制代码
usedDistance = Mathf.SmoothDamp(usedDistance, distance, ref zVelocity, 0.1f);

参考:

对应的 API 变化

2.x 3.x
CinemachineVirtualCamera CinemachineCamera
GetCinemachineComponent<CinemachinePOV>() GetCinemachineComponent(CinemachineCore.Stage.Aim) 或直接 GetComponent<CinemachinePOV>()
AddCinemachineComponent<CinemachinePOV>() gameObject.AddComponent<CinemachinePOV>()
DestroyCinemachineComponent<CinemachineComposer>() DestroyImmediate(GetComponent<CinemachineComposer>())
CinemachineFramingTransposer CinemachineFramingTransposer(保留)或 CinemachinePositionComposer
CinemachineInputProvider CinemachineInputAxisController
相关推荐
甲维斯1 天前
普通人慎入!Fable5原创游戏“死线求生”第一版!
人工智能·ai编程·游戏开发
SmalBox1 天前
【节点】[IrisOutOfBoundColorClamp节点]原理解析与实际应用
unity3d·游戏开发·图形学
郝学胜-神的一滴1 天前
[简化版 GAMES 101] 计算机图形学 16:纹理走样、Mipmap、三线性插值、各向异性过滤原理全解
unity·游戏引擎·godot·图形渲染·three.js·opengl·unreal
吴梓穆2 天前
untiy TextMeshPro (TMP) text 操作 中文字符集 字体材质操作(添加纹理 添加描边 添加阴影)
unity
SmalBox2 天前
【节点】[IrisOffset节点]原理解析与实际应用
unity3d·游戏开发·图形学
想你依然心痛2 天前
嵌入式单元测试:Unity/CMock框架与硬件在环测试——测试驱动、桩函数
unity·单元测试·游戏引擎
xcLeigh2 天前
Unity基础:Game视图详解——游戏预览、分辨率模拟与性能显示
游戏·unity·游戏引擎·音频·视频·game·play模式
xcLeigh2 天前
Unity基础:Scene视图操作完全指南——视角控制、物体选择与场景导航
unity·游戏引擎·scene·试图·场景导航
mxwin3 天前
Unity Shader exp 函数的算法与渲染应用
算法·unity·游戏引擎·shader