《Cocos 游戏开发实战》10.3 震动、顿帧与打击感
声音和特效都有了,为什么撞上障碍还是「软」?缺的是打击感的三要素:震动、顿帧、屏幕位移。本节给出跨端震动 API 的封装、一个可单测的顿帧时间缩放调度器、以及屏幕震动与白闪的可编译实现,并说清什么时候不该用打击感、哪些高频事件必须刻意克制,避免反馈滥用。
category
声音和特效都有了,为什么撞上障碍还是「软」?缺的是打击感的三要素:震动、顿帧、屏幕位移。本节给出跨端震动 API 的封装、一个可单测的顿帧时间缩放调度器、以及屏幕震动与白闪的可编译实现,并说清什么时候不该用打击感、哪些高频事件必须刻意克制,避免反馈滥用。
10.1 的 AudioManager 在桌面浏览器里跑得好好的,一上手机就哑了——浏览器的自动播放策略、微信小游戏的音频初始化、iOS 的静音开关,三端各有各的脾气。本节讲清这些限制,给出用 sys.platform 判定环境、首次交互解锁音频、以及切后台中断恢复的可编译代码。
Animation 管姿态、tween 管单属性,剩下两类动效它们都做不了:金币拾取的爆散粒子、以及要换皮换动作的角色骨骼。本节讲 Cocos 3.8 的 ParticleSystem2D 与 Spine/DragonBones 骨骼,给出编辑器配置步骤、.plist 文件在编辑器里的样子,以及一张选型与性能对照表。
上一章把玩法跑通,但关卡还是场景里手工摆的节点,加一关就要复制一份场景。本节把整关的摆放变成数据:定义 levels.json 的 schema(obstacles/coins/goalX/speed),讲清关卡局部坐标的取值口径,再把 assets/configs 配成 Bundle bundle-levels,并给出 Obstacle.prefab 与命名约定。
玩法跑通之后,真正决定留存的是一堆散落的数字。本节把《方块冲刺》的手感参数抽成一份 FeelConfig,用 @property 的 range 与 slide 暴露成可拖动的滑条,讲清 jumpVelocity 与 gravity 为什么必须成对调,再给出运行时热调、本地持久化与 feel.json 导入设置的做法。
本节把《方块冲刺》的设计分辨率锁死在 960 × 540,用 Canvas 与 UI 相机建立渲染根,用 Widget 把 HUD 钉在四角、用 SafeArea 躲开刘海与手势条,并给出编辑器里逐项可照做的操作步骤与操作后属性面板应显示的值。
本节讲清 director.addPersistRootNode 到底做了什么、目标节点必须位于层级根节点这条约束从何而来,用 PersistentRoot 承载音频、存档与转场等全局管理器,并说明常驻节点上组件 onLoad 只调一次带来的初始化陷阱与切后台自动存档的接法。
静态引用会让首包失控,动态加载是资源管线的另一半。本节讲清 resources.load、bundle.load、loadRemote 三种 API 的取舍,把回调式加载包成 Promise,用 loadDir 批量读配置表,讲透 addRef / decRef 的引用计数规则与 releaseAsset 只减引用不立即销毁的坑,并给出一个可单测的引用计数管理器与 preload 预加载。
组件之间硬引用会织出蜘蛛网。本节把 Cocos Creator 3.8 的三种通信方式摆开对比:直接引用、getComponent、事件。讲清节点事件与全局 EventTarget 总线、target 参数绑定 this 的坑、触摸坐标从屏幕到节点空间的两次换算、全局 input 与 KeyCode 接键盘跳跃,并给出编辑器里给 Button 绑定 Click Events 的步骤与场景文件结构。
进编辑器搭出 block-dash 的 main 场景:从层级管理器右键创建 Canvas 开始,讲清节点树、父子关系与变换,把可复用的金币做成预制体,用 instantiate 在运行时复制它,并打开 main.scene 看 _components 数组里的 __type__ 到底存了什么。
本节把《方块冲刺》的运营侧补齐:用一张 activities.json 描述活动与时段,纯逻辑校验时间窗、权重与互斥优先级,运行时下发并本地兜底,再定义一套埋点事件模型与看板四项核心指标,让运营能自己上活动、关活动、看数据,而不必每次改代码发版。文末给出与 17.1/17.2 共用的配置骨架与工程收口。
本节讲《方块冲刺》的热更与线上修复:先划清热更能改什么、绝不能改什么,再看资源热更的 manifest 与版本比对机制、原生端 native.AssetsManager 的完整调用时序、bundle 热更与脚本热更的边界,并给出一次线上修复的可执行流程与可类型检查的 HotUpdate 组件。
《方块冲刺》到了上线阶段,本节讲灰度与回滚:为什么小游戏比原生更需要灰度、H5 与微信小游戏与原生三端各自能用的灰度手段、远端开关与版本门的实现、按设备哈希确定性分桶、灰度期的观测指标,以及 P0/P1/P2 三套回滚预案,并给出可类型检查的 RemoteConfig 组件与纯逻辑版本门。
首包压下去了、资源上了 CDN,用户从点开到看到第一屏仍要等。本节把启动时间拆成「引擎初始化 / 脚本执行 / 首场景加载 / 首屏渲染」四段,用引擎事件打点、用纯函数聚合,给出五个可落地的削减动作与构建面板里的对应开关,并把首屏预算对齐到 1.1 的 NFR-02。
上一节把资源从首包挪进了 Bundle,但只要分包还打进包体,用户就只是把 4 MB 的红线换成了 20 MB 的总量红线。本节把 bundle-levels 改成远程包、托管到 CDN,给出构建面板里的远程地址与版本目录配置、可编译的加载脚本,以及一张按文件类型划分的缓存头策略表。
微信小游戏给主包划了 4 MB 红线,首包多塞一张背景图就可能上不了架。本节把《方块冲刺》的资源按「首包只留启动场景与主 UI、关卡资源进 bundle-levels」切开,给出编辑器里配置 Bundle 的完整步骤与 .meta 内容,并写出一个能过 tsc 的分包加载管理器。
11.1 的存档里留了个 settings.language 没实现。本节把 UI 文案外置成 JSON 资源,用 sys.languageCode 探测系统语言、允许玩家手动覆盖,写一个带插值的 i18n 核心和一个跟随语言的 Label 组件,最后对比系统字体、TTF 与位图字体三种方案,并说清微信小游戏对字体的真实限制。
同一个账号在手机和平板上各玩一局,两份进度就会打架。本节先定客户端与服务端的云存档接口约定,再给出「先拉后推」的同步时序,然后写一段可单测的字段级合并算法(最远距离取最大、资产取较新),最后按平台分派传输层:微信走云开发、H5 与原生走 HTTP。
第 9 章让《方块冲刺》动起来了,但没有声音的反馈是空的。本节从 AudioSource 讲起,说清 BGM、音效、语音三类需求的差异,给出常驻节点上的 AudioManager 组件、playOneShot 的并发上限,以及一个可单测的音效池优先级调度器。
Cocos 工程该提交什么、永远不提交什么:给出完整 .gitignore 与 Git LFS 配置,讲清 .scene/.prefab 为什么难合并、多人协作怎么切场景与预制体,定下提交信息与分支约定,写一个可单测的语义化版本比较函数,并把版本号打进运行时的 BuildStamp 组件。