Skip to content

Lesson 003|什么是 World Matrix?为什么父节点移动,子节点也会移动?

Tags: #Creator2.x #Node #Transform #Matrix #WorldMatrixDifficulty: ⭐⭐☆☆☆


🎯 本课目标

  • 理解 LocalWorld 的区别
  • 理解为什么父节点移动,子节点也会跟着移动
  • 初步理解 Matrix 在引擎中的作用
  • 为后续学习 Transform、Renderer、DirtyFlag 和性能优化打基础

🧩 上节课回顾

上一课我们讲了:

text
this.node.x = 100


Setter


Node 数据更新


Dirty Flag


等待 Renderer


World Matrix


GPU 绘制


Screen

其中有一个关键点:

修改 node.x 后,并不是立刻画到屏幕上,而是先修改节点数据,然后等待渲染阶段统一更新。

今天我们重点理解其中的:

World Matrix


💡 为什么需要 World Matrix?

假设有两个节点:

text
Parent.x = 100
Child.x  = 50

那么 Child 最终显示在屏幕上的 x 通常是:

text
100 + 50 = 150

因为 Child 的位置不是直接相对于屏幕,而是相对于父节点。

所以:

text
Child 的最终位置 = Parent 的世界位置 + Child 自己的本地位置

在没有旋转和缩放的简单情况下,可以这样理解。


🧠 Local 和 World

Local

Local 表示:

相对于父节点的坐标或变换。

例如:

ts
child.x = 50;

意思不是:

child 在屏幕上的 x 是 50。

而是:

child 相对于父节点偏移 50。

World

World 表示:

相对于整个世界 / 场景 / 屏幕参考系的最终坐标或变换。

例如:

text
Parent.x = 100
Child.x = 50

那么:

text
Child.worldX = 150

🧠 Matrix 是什么?

Matrix 中文叫:

矩阵

你现在可以先把它理解成:

一张数字表格。

例如 2D 游戏里常见的变换矩阵可以想象成:

text
[ a  c  tx ]
[ b  d  ty ]
[ 0  0  1  ]

现阶段不用纠结每个数字的数学含义。

在游戏引擎里,Matrix 的作用是:

把 position、rotation、scale 这些变换信息打包到一起。

也可以简单理解成:

Matrix = 节点的变换规则包。


🧠 Local Matrix 和 World Matrix

每个 Node 可以简单理解为有两类变换信息:

text
Local Matrix
World Matrix

Local Matrix

Local Matrix 由节点自己的属性计算出来:

text
position
rotation
scale
anchor
skew

它表示:

我相对于父节点应该怎么变换。

World Matrix

World Matrix 由父节点的 World Matrix 和自己的 Local Matrix 合成。

可以简单理解为:

text
child.worldMatrix = parent.worldMatrix * child.localMatrix

不用纠结矩阵乘法细节。

现在只需要记住:

子节点最终的世界变换,依赖父节点的世界变换。


🔍 为什么父节点移动,子节点会跟着移动?

因为子节点的 World Matrix 依赖父节点。

text
Parent worldMatrix 变化


Child worldMatrix 也需要重新计算


Child 显示位置变化

所以:

ts
parent.x = 100;

即使子节点自己的 x 没有变化,它在屏幕上的位置也会变化。

因为:

子节点 local 没变,但它依赖的父节点 world 变了。


💼 工作中的真实案例

案例一:复杂 UI 面板移动

假设有一个活动面板:

text
ActivityPanel
├── Background
├── Title
├── CloseButton
├── RewardList
├── CountDownLabel
├── Effect
└── ManyItems

如果每帧移动整个面板:

ts
this.panel.x += 10;

看起来只改了一个节点。

但实际上可能影响:

  • Panel 自己
  • Panel 下所有子节点
  • 子节点的 World Matrix
  • 子节点的渲染顶点数据

所以复杂 UI 面板移动时,CPU 可能会上升。

案例二:ScrollView 列表

ScrollView 中如果存在大量 item,并且频繁修改 item 的位置,可能导致大量节点矩阵更新。

所以大型列表通常需要:

  • 虚拟列表
  • item 复用
  • 减少节点数量
  • 减少频繁 Layout

案例三:Layout / Widget 频繁刷新

Layout 或 Widget 会修改子节点的位置。

如果它们每帧都刷新,就会导致大量子节点反复 Dirty。

性能优化时要重点关注:

是否有 Layout、Widget、ScrollView 在频繁触发 Transform 更新。


⚠️ 常见误区

误区一:child.x 就是屏幕坐标

不是。

child.x 通常是本地坐标,是相对于父节点的。

误区二:只改父节点,不会影响子节点

会影响。

父节点的 World Matrix 变化后,子节点的最终世界变换也会变化。

误区三:矩阵太难,所以可以完全不学

不用一开始学复杂数学。

先理解它的工程意义:

Matrix 是引擎统一处理位移、旋转、缩放的工具。


🎤 面试会怎么问

问题一:Cocos 中 node.position 是世界坐标还是本地坐标?

参考回答:

通常是本地坐标,相对于父节点。真正渲染时,引擎会结合父节点变换计算出世界坐标。

问题二:为什么移动父节点,所有子节点都会跟着移动?

参考回答:

因为子节点的 World Matrix 依赖父节点的 World Matrix。父节点变换发生变化后,子节点的世界矩阵也需要重新计算。

问题三:为什么一个复杂 UI 面板移动时可能会卡?

参考回答:

因为移动父节点会导致整棵子树的世界矩阵变脏,渲染前需要重新计算大量节点的矩阵和顶点数据。


📝 今日练习

假设有下面结构:

text
Root
└── Panel
    └── Button

属性如下:

text
Root.x = 0
Panel.x = 100
Button.x = 30

回答:

  1. Button 的 world x 是多少?
  2. 如果 Panel.x 改成 200,Button 的 world x 是多少?
  3. 这个过程中 Button 自己的 x 有没有变化?
  4. 为什么 Button 显示位置变了?

📝 今日练习参考答案

  1. Button 的 world x 是:
text
0 + 100 + 30 = 130
  1. 如果 Panel.x 改成 200,Button 的 world x 是:
text
0 + 200 + 30 = 230
  1. Button 自己的 x 没有变化,仍然是:
text
Button.x = 30
  1. Button 显示位置变了,是因为父节点 Panel 的位置变了。Button 的 local 坐标没变,但它的 world 坐标依赖父节点。

🚀 能力成长

学完这一课后,你应该具备以下能力:

  • 能解释 Local 坐标和 World 坐标的区别
  • 能解释为什么父节点移动,子节点也会移动
  • 能理解 Matrix 是节点变换规则的数字化表示
  • 能初步分析复杂 UI 移动导致 CPU 上升的原因
  • 能为后续学习 Transform、DirtyFlag、Renderer 打基础

✅ 本课总结

记住四句话:

text
Local 是相对于父节点。
World 是最终显示到世界中的位置。
Matrix 是节点变换规则包。
父节点变了,子节点的 World Matrix 也会受影响。

下一课: Transform 为什么要分 position、rotation、scale?