主题切换
06 引擎深度实战
预计阅读 30 分钟
版本信息
最后更新:2026-07-09 · 推荐引擎版本:Cocos Creator 3.8.8 LTS · 适用基础库:≥ 3.9.0(最低兼容 ≥ 2.30.0)
📢 2026年1月 Cocos 4.0 已正式发布(MIT 开源,引擎/编辑器分离)。本章内容基于成熟的 3.8.8 LTS,Cocos 4.0 相关内容将逐步更新。
📢 2026年1月 Cocos 4.0 已正式发布(MIT 开源,引擎/编辑器分离)。本章内容基于成熟的 3.8.8 LTS,Cocos 4.0 相关内容将逐步更新。
本章以 Cocos Creator 为主引擎进行深度实战讲解,同时提供跨引擎的概念对照,帮助你理解引擎的本质抽象。
6.1 Cocos Creator 核心 workflow
项目结构
hello-world/
├── assets/ # 资源目录(场景、脚本、预制体)
│ ├── scenes/ # 场景文件 (.scene)
│ ├── scripts/ # 脚本文件 (.ts)
│ ├── prefabs/ # 预制体 (.prefab)
│ └── textures/ # 贴图资源
├── settings/ # 项目设置
└── build/ # 构建输出核心节点:Node + Component
typescript
// Cocos Creator 组件模式
import { _decorator, Component, Node } from 'cc'
const { ccclass, property } = _decorator
@ccclass('PlayerController')
export class PlayerController extends Component {
@property
speed: number = 200
start() {
// 组件挂载到节点时调用一次
}
update(deltaTime: number) {
// 每帧调用
const pos = this.node.position
this.node.setPosition(pos.x + this.speed * deltaTime, pos.y, pos.z)
}
onDestroy() {
// 组件销毁时调用
}
}前端对比:React 组件 vs Cocos Component
| 维度 | React 组件 | Cocos Component |
|---|---|---|
| 挂载方式 | JSX 声明 <Comp /> | 拖拽到节点上 |
| Props / 属性 | props 传入 | @property 装饰器 + 编辑器面板 |
| 生命周期 | mount/update/unmount | onLoad/start/update/onDestroy |
| 子节点 | children prop | this.node.children |
| 复用方式 | 组件复用 render | 预制体 (Prefab) 实例化 |
| 状态管理 | useState / store | 直接在 Component 属性上维护 |
| 数据流 | Virtual DOM diff → 增量更新 | 每帧全量更新 → 直接操作 GPU |
核心差异: React 是声明式的("状态变了 UI 自动反映");Cocos Component 是命令式的("每一帧你要显式告诉我每个节点在哪")。React 的 useEffect 依赖数组 → Cocos 的 update(dt) 每帧无条件执行。适应技巧: 把 update(dt) 想象成每 16ms 调用一次的全量 "render",游戏没有"增量更新"的概念,每一帧都是全量。
6.2 跨引擎概念映射
| 概念 | Cocos Creator | Unity | LayaAir | 原生 Canvas |
|---|---|---|---|---|
| 游戏对象 | Node | GameObject | Sprite/Node | 手动管理 |
| 组件模式 | Component | MonoBehaviour | Script | 无对应 |
| 场景 | Scene | Scene | Scene | 状态机 |
| 生命周期 | onLoad/start/update | Awake/Start/Update | onAwake/onStart/onUpdate | 手动管理 |
| 碰撞系统 | Collider2D/3D | Collider2D/3D | Physics | 手写算法 |
| 预制体 | Prefab | Prefab | Prefab | 工厂函数 |
| 资源加载 | resources.load | Resources.Load | Laya.loader.load | Image.onload |
引擎的本质
引擎 = 可视化编辑器 + 组件系统 + 场景管理 + 渲染封装 + 平台适配
一旦你理解了游戏循环、碰撞检测、状态机等核心概念(第三章),不同引擎之间的切换无非是学习新的 API 名称和编辑器操作。不要被引擎绑定,要理解引擎背后的通用原理。
6.3 Flappy Bird Cocos Creator 完整实战
本节以 Flappy Bird 为贯穿项目,展示如何在 Cocos Creator 中从零搭建一个完整游戏。完整源码参考 Flappy Bird Cocos 实战。
6.3.1 创建项目与场景搭建
- 打开 Cocos Dashboard → 新建项目 → 选择「Empty」模板
- 项目创建完成后,在
assets/下建立目录结构:
assets/
├── scenes/ # 场景文件
│ ├── Start.scene # 开始界面
│ ├── Game.scene # 游戏主场景
│ └── GameOver.scene # 结束界面
├── scripts/ # 脚本文件
│ ├── GameController.ts
│ ├── BirdController.ts
│ ├── PipeSpawner.ts
│ └── PipeMover.ts
├── prefabs/ # 预制体
│ ├── Bird.prefab
│ └── Pipe.prefab
└── textures/ # 图片资源(精灵图、背景等)6.3.2 核心脚本实现
BirdController — 小鸟物理与输入
typescript
import { _decorator, Component, RigidBody2D, Vec2, input, Input, EventTouch } from 'cc'
const { ccclass } = _decorator
@ccclass('BirdController')
export class BirdController extends Component {
private rigidBody: RigidBody2D | null = null
private isDead: boolean = false
start() {
this.rigidBody = this.getComponent(RigidBody2D)
// 设置重力缩放,值越大下落越快(默认 gravityScale 在编辑器 RigidBody2D 组件中配置)
// 如果希望在代码中动态控制,可取消下面注释:
// if (this.rigidBody) this.rigidBody.gravityScale = 3
input.on(Input.EventType.TOUCH_START, this.onTouch, this)
}
onTouch() {
if (this.isDead) return
// 施加向上的瞬时力(模拟点击飞翔)
if (this.rigidBody) {
this.rigidBody.linearVelocity = Vec2.ZERO
this.rigidBody.applyForceToCenter(new Vec2(0, 800), true)
}
}
onDestroy() {
input.off(Input.EventType.TOUCH_START, this.onTouch, this)
}
}PipeSpawner — 管道生成与回收
typescript
import { _decorator, Component, Prefab, instantiate, Node } from 'cc'
const { ccclass, property } = _decorator
@ccclass('PipeSpawner')
export class PipeSpawner extends Component {
@property(Prefab)
pipePrefab: Prefab = null!
@property
spawnInterval: number = 2
@property
gapSize: number = 200
private timer: number = 0
private pipePool: Node[] = []
update(deltaTime: number) {
this.timer += deltaTime
if (this.timer >= this.spawnInterval) {
this.timer = 0
this.spawnPipe()
}
}
spawnPipe() {
const pipe = instantiate(this.pipePrefab)
const randomY = Math.random() * 200 - 100 // 随机偏移
pipe.setPosition(480, randomY) // 从右侧屏幕外出现
this.node.addChild(pipe)
this.pipePool.push(pipe)
}
}6.3.3 场景管理与状态控制
Cocos Creator 通过 director.loadScene() 在场景间切换:
typescript
import { director } from 'cc'
// 从开始界面跳转到游戏场景
director.loadScene('Game')
// 使用 preloadScene 预加载场景以减少切换时的卡顿
director.preloadScene('Game', () => {
console.log('Game scene preloaded')
})6.3.4 物理系统接入
Cocos Creator 内置 Box2D 物理引擎,碰撞检测无需手写算法:
- 为小鸟和管道节点添加
RigidBody2D组件 - 添加
BoxCollider2D定义碰撞区域 - 在脚本中监听碰撞事件:
typescript
import { Collider2D, Contact2DType, IPhysics2DContact } from 'cc'
this.getComponent(Collider2D)?.on(
Contact2DType.BEGIN_CONTACT,
(self: Collider2D, other: Collider2D, contact: IPhysics2DContact | null) => {
if (other.node.name === 'Pipe') {
this.gameOver()
}
},
this
)6.3.5 构建发布为微信小游戏
- 主菜单 → 项目 → 构建发布
- 平台选择「微信小游戏 (WeChat Mini Game)」
- 配置
appid和输出目录 - 点击「构建」→ 再用微信开发者工具打开构建产物目录
- 在微信开发者工具中预览、调试、上传
6.4 Unity 小游戏插件实战
如果你选择 Unity 作为引擎,微信官方提供了 WX-WASM-SDK 插件将 Unity WebGL 导出适配到微信小游戏环境。
6.4.1 环境准备
- 安装 Unity 2022.3 LTS(或团结引擎最新稳定版)
- 下载 微信小游戏 Unity 插件
- 通过
Package Manager→Add package from git URL安装
6.4.2 项目结构迁移
Unity 项目根/
├── Assets/
│ ├── Scripts/ # C# 脚本(对应 Cocos 的 scripts/)
│ ├── Scenes/ # 场景文件(.unity,对应 .scene)
│ ├── Prefabs/ # 预制体(对应 .prefab)
│ └── Resources/ # 动态加载资源
├── Packages/
└── WX-WASM-SDK/ # 微信适配插件6.4.3 TypeScript → C# 关键概念映射
| TypeScript (Cocos) | C# (Unity) | 说明 |
|---|---|---|
@ccclass | MonoBehaviour | 组件基类 |
start() | Start() / Awake() | 初始化方法 |
update(dt) | Update() / FixedUpdate() | 每帧更新 |
@property | [SerializeField] | 面板可见属性 |
this.node.position | transform.position | 位置信息 |
instantiate(prefab) | Instantiate(prefab) | 实例化预制体 |
director.loadScene | SceneManager.LoadScene | 场景切换 |
6.4.4 调用微信 API
Unity 中通过 WX 命名空间即可直接调用微信 API:
csharp
using WeChatWASM;
// 分享
WX.ShareAppMessage(new ShareAppMessageOption
{
title = "快来玩我的游戏!",
imageUrl = "share.png"
});
// 登录
WX.Login(new LoginOption
{
success = (res) => {
Debug.Log("code: " + res.code);
}
});
// 激励视频广告
WX.CreateRewardedVideoAd(new WXCreateRewardedVideoAdParam
{
adUnitId = "adunit-xxx"
});6.4.5 构建发布流程
File→Build Settings→ 切换到 WebGL 平台Player Settings→ 调整分辨率和内存- 菜单栏:
微信小游戏→Build WebGL & 微信小游戏 - 用微信开发者工具打开构建产物
引擎选择建议
如果你主要做 3D 或想做跨平台(iOS/Android 原生 + 小游戏),Unity 是更好的选择。如果专注于微信小游戏 2D 休闲游戏,Cocos Creator 的 TypeScript 栈和微信适配更成熟。
6.5 LayaAir IDE 速览
LayaAir 是国内另一款成熟的小游戏引擎,在 2D 重度游戏和页游转型小游戏场景中有独特优势。
6.5.1 与 Cocos Creator 的核心差异
| 维度 | Cocos Creator | LayaAir |
|---|---|---|
| IDE 风格 | 接近 Unity 的分区面板 | 更接近 Flash/Animate 的时间轴布局 |
| 脚本语言 | TypeScript | TypeScript / JavaScript / ActionScript 3 |
| 组件模型 | @ccclass 装饰器 | 继承 Laya.Script |
| 2D 渲染 | 基于 Sprite 合批 | 基于 drawCall 优化的渲染管线 |
| 3D 支持 | 内置 3D(3.8+) | LayaAir 3.0 开始支持 |
| UI 系统 | 内置 UI 组件 | 独立的 Laya.UI 命名空间 |
| 最佳场景 | 2D/3D 混合、快速原型 | 2D 重度(MMO/卡牌)、页游转型 |
6.5.2 脚本写法对比
typescript
@ccclass('MyComponent')
export class MyComponent extends Component {
@property speed: number = 100
update(dt: number) {
/* ... */
}
}核心差异:LayaAir 不依赖装饰器,属性无法在编辑器中可视化编辑(需通过 owner 节点手动获取),但脚本生命周期钩子(onAwake/onEnable/onUpdate/onDisable)命名更加直观。
6.5.3 快速上手路径
- 下载 LayaAir IDE → 新建项目 → 选择「空项目」
- 熟悉 IDE 面板:场景树 / 属性面板 / 项目资源 / 时间轴
- 在场景中添加 2D 精灵 → 挂载脚本 → 预览
- 构建发布:IDE 工具栏 → 发布 → 微信小游戏
LayaAir 学习建议
如果你是前端转型且目标做 2D 重度游戏(卡牌、MMO、SLG),LayaAir 的 TypeScript 栈 + 2D 渲染性能是一个值得评估的选择。但社区规模和第三方资源较 Cocos Creator 少,遇到问题时自行排查的比例更高。
6.6 多引擎项目迁移指南
在实际项目中,你可能因为团队变动、性能需求或平台策略调整而在引擎间迁移。本节提供系统化的迁移指南。
6.6.1 迁移核心原则:引擎不可知论 (Engine-Agnostic)
将游戏逻辑与引擎 API 解耦是降低迁移成本的根本方法:
typescript
// ❌ 紧耦合写法(迁移困难)
import { Vec2, RigidBody2D } from 'cc' // 直接依赖 Cocos API
// ✅ 引擎无关写法(可迁移)
interface IPhysicsBody {
applyForce(force: { x: number; y: number }): void
setVelocity(vel: { x: number; y: number }): void
}
// 游戏逻辑只依赖接口
class PlayerLogic {
constructor(private body: IPhysicsBody) {}
jump() {
this.body.applyForce({ x: 0, y: 800 })
}
}
// 各引擎分别实现 Adapter
class CocosPhysicsBody implements IPhysicsBody {
/* 封装 Cocos API */
}
class UnityPhysicsBody implements IPhysicsBody {
/* 封装 Unity API */
}这种 Adapter 模式虽然初期会增加代码量,但长期来看大幅降低引擎锁定的风险。
6.6.2 迁移检查清单
| 迁移方向 | 关键工作项 | 预估耗时 |
|---|---|---|
| Cocos → Unity | 脚本重写 (TS→C#)、场景重建、物理系统适配 | 4-8 周 |
| Unity → Cocos | 脚本重写 (C#→TS)、第三方插件替换 | 3-6 周 |
| Cocos 2.x → 3.x | API 更新、渲染管线升级 | 2-4 周 |
| LayaAir → Cocos | 脚本适配、时间轴替换、UI 重构 | 4-8 周 |
6.6.3 资源格式兼容表
| 资源类型 | Cocos | Unity | LayaAir | 通用迁移方案 |
|---|---|---|---|---|
| 纹理/精灵 | PNG/JPG/WebP | PNG/JPG/TGA | PNG/JPG | 直接复用 |
| 音频 | MP3/WAV/OGG | MP3/WAV/OGG | MP3/WAV | 直接复用 |
| 字体 | TTF/Bitmap | TTF/SDF | TTF/Bitmap | 注意各引擎文字渲染差异 |
| 骨骼动画 | Spine/DragonBones | 需要第三方插件 | Spine/DragonBones | Spine 格式相对通用 |
| 场景/关卡 | .scene (JSON) | .unity (YAML) | .ls (JSON) | 无法直接迁移,需手动重建 |
| 预制体 | .prefab | .prefab | .lh | 同上 |
6.6.4 迁移决策框架
在决定是否迁移引擎前,先回答以下问题:
引擎迁移决策树:
├── 当前引擎还能满足核心需求吗?
│ ├── 是 → 不迁移,优化现有项目
│ └── 否 → 继续
│ ├── 迁移成本 < 重写成本 → 执行迁移
│ └── 迁移成本 > 重写成本 → 新项目用新引擎,老项目维护降低迁移成本的 4 个习惯
- 业务逻辑与引擎 API 分离 — 核心玩法逻辑不直接 import 引擎 API
- 数据驱动设计 — 关卡数据、配置表用 JSON/CSV,不硬编码在组件属性中
- 统一资源命名规范 — 纹理、音频、动画命名在各引擎间保持一致
- 尽早接入 CI/CD — 构建脚本可以在引擎切换时快速验证功能完整性
📝 课后练习
练习 1:Cocos Creator 组件生命周期
题目: 说明 Cocos Creator Component 的 onLoad、start、update、onDestroy 四个生命周期方法的调用顺序和使用场景。
参考答案:
onLoad:组件首次挂载到节点时调用,用于初始化属性、获取其他组件引用。此时场景中其他组件可能未就绪start:在第一次update之前调用,用于依赖其他组件已就绪的初始化。此时所有onLoad都已执行完毕update(dt):每帧调用,核心游戏逻辑的更新入口onDestroy:组件被移除时调用,用于清理事件监听、释放资源,防止内存泄漏
练习 2:跨引擎迁移
题目: 设计一个简单的"移动实体"接口,它可以在 Cocos Creator 和 Unity 中分别用 Adapter 模式实现。
参考答案:
typescript
// 引擎无关接口
interface IMovable {
moveTo(x: number, y: number): void
getPosition(): { x: number; y: number }
}
// Cocos: class CocosMover implements IMovable { this.node.setPosition(x, y) }
// Unity: class UnityMover : IMovable { transform.position = new Vector3(x, y, 0) }📚 相关阅读
- 05 引擎对比与选型 — 实战前的引擎选型决策框架
- Flappy Bird Cocos 实战 — Cocos Creator 版本完整源码
- 08 性能优化与包体控制 — 引擎项目性能调优
- 跨引擎概念映射速查 — 多引擎概念快速对照