在这里插入图片描述

网罗开发 (小红书、快手、视频号同名)

  大家好,我是 展菲,目前在上市企业从事人工智能项目研发管理工作,平时热衷于分享各种编程领域的软硬技能知识以及前沿技术,包括iOS、前端、Harmony OS、Java、Python等方向。在移动端开发、鸿蒙开发、物联网、嵌入式、云原生、开源等领域有深厚造诣。

图书作者:《ESP32-C3 物联网工程开发实战》
图书作者:《SwiftUI 入门,进阶与实战》
超级个体:COC上海社区主理人
特约讲师:大学讲师,谷歌亚马逊分享嘉宾
科技博主:华为HDE/HDG

我的博客内容涵盖广泛,主要分享技术教程、Bug解决方案、开发工具使用、前沿科技资讯、产品评测与使用体验。我特别关注云服务产品评测、AI 产品对比、开发板性能测试以及技术报告,同时也会提供产品优缺点分析、横向对比,并分享技术沙龙与行业大会的参会体验。我的目标是为读者提供有深度、有实用价值的技术洞察与分析。

展菲:您的前沿技术领航员
👋 大家好,我是展菲!
📱 全网搜索“展菲”,即可纵览我在各大平台的知识足迹。
每周定时推送干货满满的技术长文,从新兴框架的剖析到运维实战的复盘,助您技术进阶之路畅通无阻。


引言

很多开发者做鸿蒙游戏时,都会有一个目标:

60FPS

因为:

60FPS = 流畅

于是优化过程往往变成:

看FPS
↓
掉帧
↓
优化

但做过大型项目后你会发现一个有趣现象:

FPS显示60
玩家却觉得卡

甚至:

平均FPS 58
体验比平均FPS 90更好

为什么?因为:

玩家感受到的不是 FPS,而是帧时间(Frame Time)。

真正决定体验的不是:

跑得多快

而是:

跑得稳不稳

一、60FPS 到底意味着什么?

很多人知道:

60FPS

却不知道它真正代表什么,实际上:

1000ms ÷ 60
≈ 16.67ms

意味着:

每一帧只有 16.67ms 的预算。

这一帧里需要完成:

输入处理
System计算
状态更新
布局计算
渲染提交
GPU绘制

全部流程,只要某个环节超时:

16ms
↓
25ms

玩家就会看到:

卡顿

二、FPS 稳定比 FPS 高更重要

看两个例子:

方案A

120
120
120
25
120
120

平均:

104 FPS

方案B

58
60
59
60
61
60

平均:

59 FPS

实际上:

方案B体验更好

因为:

Frame Time稳定

所以:

优化目标不是冲高 FPS,而是消灭慢帧。

三、鸿蒙游戏为什么会掉帧?

很多人认为:

GPU不够强

实际上更多时候是:

System过重

例如:

update() {

  updateAI()

  updateEnemy()

  updatePath()

  updateMission()

  updateDrop()

}

看起来正常,但如果:

100个怪物
100次寻路
100次AI决策

瞬间就会超出:

16ms预算

四、性能预算思维

大型游戏都会做:

Frame Budget

即:

总预算:16.67ms

拆分:

System      5ms

Store       2ms

UI          4ms

Render      5ms

这样总计 < 16ms才能稳定。

五、第一原则:不要每帧做所有事情

很多人写:

update() {

  updateEnemy()

  updateAI()

  updateMission()

  updateShop()

}

每帧执行,实际上:

没必要

例如,任务系统:1秒更新一次足够;商城系统:打开时更新即可。

正确思路:

按频率执行

六、AISystem 分帧更新

错误:

enemies.forEach(enemy => {
  enemy.updateAI()
})

100个敌人:

100次AI

优化:

enemies.forEach((enemy,index) => {

  if ((frame + index) % 5 == 0) {
    enemy.updateAI()
  }

})

效果:

AI负载平均分摊

这也是大型游戏常见方案。

七、第二原则:减少状态更新风暴

例如:

store.hp--
store.gold++
store.exp++
store.level++

看起来正常,实际上:

4次通知
4次刷新

正确做法:

store.batch(() => {

  store.hp--
  store.gold++
  store.exp++
  store.level++

})

统一提交,结果一次刷新即可。

八、第三原则:Store 必须拆分

很多项目喜欢:

GameStore

管理全部状态。例如:

玩家
背包
技能
任务
商城

全部放一起。

问题:

金币变化
整个UI刷新

正确拆分:

PlayerStore

SkillStore

MissionStore

InventoryStore

这样:

局部变化
局部刷新

九、第四原则:避免频繁创建对象

很多掉帧来自:

GC

即垃圾回收,例如:

update() {

  const pos = {
    x: player.x,
    y: player.y
  }

}

每帧创建。

60FPS:

1秒60次

100个对象:

6000次创建

最终:

GC触发
↓
掉帧

优化:

pos.x = player.x
pos.y = player.y

对象复用。

十、第五原则:HUD 独立更新

很多项目:

GamePage

负责:

血条
技能
地图
任务
Boss

全部内容。

结果:

HP变化
整个页面刷新

推荐:

PlayerHUD

SkillHUD

BossHUD

MiniMapHUD

独立组件。

这样:

血量变化
只刷新血条

十一、第六原则:减少布局计算

很多人关注:

绘制性能

却忽略:

布局性能

例如:

Column()

嵌套20层以上,每次刷新重新计算布局成本极高。

优化原则:

减少嵌套
减少动态布局

十二、System 架构为什么更容易稳定 60FPS?

传统做法:

UI
↓
业务逻辑
↓
刷新UI

容易形成:

循环依赖

System架构:

Input
 ↓
System
 ↓
Store
 ↓
UI

职责明确,每层开销更容易控制。

例如:

BattleSystem

AISystem

MissionSystem

独立统计耗时,容易定位问题。

十三、帧监控 Demo

开发阶段建议加入:

const start = Date.now()

engine.update()

const cost = Date.now() - start

if (cost > 16) {
  console.warn(
    `Slow Frame: ${cost}ms`
  )
}

输出:

Slow Frame: 24ms
Slow Frame: 31ms

快速发现问题。

十四、未来优化方向:System 调度器

大型项目最终会演化出:

GameEngine

调度层,例如:

BattleSystem
AISystem
MissionSystem

统一管理,结构:

GameEngine
      ↓
 Scheduler
      ↓
 Systems

调度器负责:

分帧执行
优先级执行
延迟执行

进一步稳定帧率。

十五、一个关键认知升级

初学者认为:

60FPS
=
性能好

进阶开发者认为:

Frame Time稳定
=
性能好

而大型项目最终理解:

稳定 60FPS 的本质,不是渲染优化,而是控制每一帧的工作量。

因为任何设备:

CPU再强
GPU再快

都无法承受:

无限增长的System复杂度

总结

鸿蒙游戏实现稳定 60FPS 的核心原则:

控制Frame Budget
分帧执行System
批量更新Store
拆分状态域
减少GC
拆分HUD
降低布局成本

推荐架构:

Input
  ↓
GameEngine
  ↓
System
  ↓
Store
  ↓
HUD
  ↓
UI

最终你会发现:

鸿蒙游戏的性能优化,本质上不是优化渲染,而是让 System 在每个 16ms 周期内稳定完成状态演化。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐