Skip to content

Lesson 002|this.node.x = 100 到底发生了什么? ​

Tags: #Creator2.x #Node #DirtyFlag #RendererDifficulty: ⭐☆☆☆☆


🎯 本课目标 ​

理解一行代码从修改数据到最终显示在屏幕上的完整流程。


🧩 上节课回顾 ​

上一课我们建立了 Creator 2.x 的双路径架构:Web 和 Native 共享业务语义,但不保证经过相同的内部模块。

今天开始,我们沿着一行代码真正走一遍。


🧠 先建立稳定流程 ​

text
业务写入 node.x
        ↓
Node 本地 Transform 状态改变
        ↓
相关 Transform 被标记为需要更新
        ↓
后续阶段读取新的本地/世界变换
        ↓
可见组件准备或复用渲染数据
        ↓
Renderer 按 Camera、Material、状态和顺序组织提交
        ↓
GPU 在对应 Pass 中生成像素

这是职责模型,不是 Creator 2.4.x 所有平台的逐行源码。Web 与 Native 的字段、Binding 和渲染后端可能不同,但“先改变状态,后续系统消费状态”是稳定理解。


💡 为什么需要 Dirty Flag? ​

如果每修改一次属性都立刻完成整棵子树矩阵、顶点和 GPU 提交:

  • CPU 重复计算
  • 大量无效开销

因此引擎使用 Dirty Flag(脏标记) 或类似失效机制:

修改时记录“旧结果不能再使用”,真正计算在需要该结果的阶段发生。

延迟更新的价值是合并重复修改,但不保证每种数据都只计算一次。代码在更新后立刻主动读取世界变换、多个 Camera/Pass 消费状态,或者中途再次修改,都可能产生额外工作。


💼 第一步:同一帧连续修改 ​

ts
node.x = 100;
node.y = 200;
node.rotation = 45;
node.scale = 2;

通常这些写入先改变同一 Node 的本地状态,后续消费者只需要最终值。稳定结论不是“World Matrix 一定只算一次、GPU 一定只画一次”,而是中间三个值不会自动产生三张屏幕画面。

💼 第二步:加入父节点 ​

text
Panel
└── Icon

Icon.x 是相对 Panel 的本地坐标。Panel 的位置、旋转或缩放变化时,Icon 自己的 x 没变,但它的世界矩阵结果会变化。脏状态可能沿子树传播,因此一个父节点修改可能影响大量后代。

💼 第三步:加入渲染条件 ​

Node 本身不直接产生 DrawCall。只有可见渲染组件、Camera、Material、Texture、Blend/Stencil、层级顺序等条件共同满足,Renderer 才组织提交。一个 Node 也可能不绘制、被多个 Camera 绘制,或者经过多个 Pass。

🧭 项目中怎么判断成本 ​

text
只改 Transform → 看子树规模和 Transform 更新
改 SpriteFrame/尺寸 → 可能影响 RenderData、UV、批次
改 Material → 可能改变 Pass 和合批
增加 Camera/RenderTarget → 可能重复提交或绘制
屏幕覆盖变大 → DrawCall 不变也可能增加 GPU 像素成本

⚠️ 常见误区 ​

误区:

修改 node.x 图片就立刻移动。

实际上:

修改的是运行时状态;Renderer 和 GPU 在后续阶段消费状态。业务代码返回不等于屏幕像素已经更新。


🎤 面试会怎么问 ​

  1. 什么是 Dirty Flag?
  2. 为什么引擎喜欢延迟更新?
  3. 为什么 World Matrix 不立即计算?

📝 今日练习与推导答案 ​

问题:

ts
node.x = 100;
node.y = 200;
node.rotation = 45;
node.scale = 2;

问题一:这四次写入会产生四帧画面吗? ​

不会。它们在同一段同步业务代码中更新状态,画面由后续帧阶段统一消费最终状态。

问题二:能否因此断定世界矩阵只计算一次? ​

不能。延迟更新允许合并,但主动读取、父子传播、多个系统消费和中途再次修改都可能改变实际次数。需要锁定版本和调用条件判断。

问题三:能否因此断定只有一个 DrawCall? ​

不能。DrawCall 由渲染组件、Camera、Material、Texture、RenderState、顺序和 Pass 决定,不由“修改了几次 x”直接决定。


✅ 本课总结 ​

以后分析性能问题,先判断发生在哪一层:

业务状态 → Transform/组件数据 → Renderer → GPU

下一课: 什么是 World Matrix?为什么父节点移动,子节点也会移动?