Skip to content

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 相关内容将逐步更新。

本章以 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/unmountonLoad/start/update/onDestroy
子节点children propthis.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 CreatorUnityLayaAir原生 Canvas
游戏对象NodeGameObjectSprite/Node手动管理
组件模式ComponentMonoBehaviourScript无对应
场景SceneSceneScene状态机
生命周期onLoad/start/updateAwake/Start/UpdateonAwake/onStart/onUpdate手动管理
碰撞系统Collider2D/3DCollider2D/3DPhysics手写算法
预制体PrefabPrefabPrefab工厂函数
资源加载resources.loadResources.LoadLaya.loader.loadImage.onload
引擎的本质

引擎 = 可视化编辑器 + 组件系统 + 场景管理 + 渲染封装 + 平台适配

一旦你理解了游戏循环、碰撞检测、状态机等核心概念(第三章),不同引擎之间的切换无非是学习新的 API 名称和编辑器操作。不要被引擎绑定,要理解引擎背后的通用原理。


6.3 Flappy Bird Cocos Creator 完整实战

本节以 Flappy Bird 为贯穿项目,展示如何在 Cocos Creator 中从零搭建一个完整游戏。完整源码参考 Flappy Bird Cocos 实战

6.3.1 创建项目与场景搭建

  1. 打开 Cocos Dashboard → 新建项目 → 选择「Empty」模板
  2. 项目创建完成后,在 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 物理引擎,碰撞检测无需手写算法:

  1. 为小鸟和管道节点添加 RigidBody2D 组件
  2. 添加 BoxCollider2D 定义碰撞区域
  3. 在脚本中监听碰撞事件:
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 构建发布为微信小游戏

  1. 主菜单 → 项目 → 构建发布
  2. 平台选择「微信小游戏 (WeChat Mini Game)」
  3. 配置 appid 和输出目录
  4. 点击「构建」→ 再用微信开发者工具打开构建产物目录
  5. 在微信开发者工具中预览、调试、上传

6.4 Unity 小游戏插件实战

如果你选择 Unity 作为引擎,微信官方提供了 WX-WASM-SDK 插件将 Unity WebGL 导出适配到微信小游戏环境。

6.4.1 环境准备

  1. 安装 Unity 2022.3 LTS(或团结引擎最新稳定版)
  2. 下载 微信小游戏 Unity 插件
  3. 通过 Package ManagerAdd 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)说明
@ccclassMonoBehaviour组件基类
start()Start() / Awake()初始化方法
update(dt)Update() / FixedUpdate()每帧更新
@property[SerializeField]面板可见属性
this.node.positiontransform.position位置信息
instantiate(prefab)Instantiate(prefab)实例化预制体
director.loadSceneSceneManager.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 构建发布流程

  1. FileBuild Settings → 切换到 WebGL 平台
  2. Player Settings → 调整分辨率和内存
  3. 菜单栏:微信小游戏Build WebGL & 微信小游戏
  4. 用微信开发者工具打开构建产物
引擎选择建议

如果你主要做 3D 或想做跨平台(iOS/Android 原生 + 小游戏),Unity 是更好的选择。如果专注于微信小游戏 2D 休闲游戏,Cocos Creator 的 TypeScript 栈和微信适配更成熟。


6.5 LayaAir IDE 速览

LayaAir 是国内另一款成熟的小游戏引擎,在 2D 重度游戏和页游转型小游戏场景中有独特优势。

6.5.1 与 Cocos Creator 的核心差异

维度Cocos CreatorLayaAir
IDE 风格接近 Unity 的分区面板更接近 Flash/Animate 的时间轴布局
脚本语言TypeScriptTypeScript / 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 快速上手路径

  1. 下载 LayaAir IDE → 新建项目 → 选择「空项目」
  2. 熟悉 IDE 面板:场景树 / 属性面板 / 项目资源 / 时间轴
  3. 在场景中添加 2D 精灵 → 挂载脚本 → 预览
  4. 构建发布: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.xAPI 更新、渲染管线升级2-4 周
LayaAir → Cocos脚本适配、时间轴替换、UI 重构4-8 周

6.6.3 资源格式兼容表

资源类型CocosUnityLayaAir通用迁移方案
纹理/精灵PNG/JPG/WebPPNG/JPG/TGAPNG/JPG直接复用
音频MP3/WAV/OGGMP3/WAV/OGGMP3/WAV直接复用
字体TTF/BitmapTTF/SDFTTF/Bitmap注意各引擎文字渲染差异
骨骼动画Spine/DragonBones需要第三方插件Spine/DragonBonesSpine 格式相对通用
场景/关卡.scene (JSON).unity (YAML).ls (JSON)无法直接迁移,需手动重建
预制体.prefab.prefab.lh同上

6.6.4 迁移决策框架

在决定是否迁移引擎前,先回答以下问题:

引擎迁移决策树:
├── 当前引擎还能满足核心需求吗?
│   ├── 是 → 不迁移,优化现有项目
│   └── 否 → 继续
│       ├── 迁移成本 < 重写成本 → 执行迁移
│       └── 迁移成本 > 重写成本 → 新项目用新引擎,老项目维护
降低迁移成本的 4 个习惯
  1. 业务逻辑与引擎 API 分离 — 核心玩法逻辑不直接 import 引擎 API
  2. 数据驱动设计 — 关卡数据、配置表用 JSON/CSV,不硬编码在组件属性中
  3. 统一资源命名规范 — 纹理、音频、动画命名在各引擎间保持一致
  4. 尽早接入 CI/CD — 构建脚本可以在引擎切换时快速验证功能完整性

📝 课后练习

练习 1:Cocos Creator 组件生命周期

题目: 说明 Cocos Creator Component 的 onLoadstartupdateonDestroy 四个生命周期方法的调用顺序和使用场景。

参考答案:

  • 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) }

📚 相关阅读

用心学习,持续实践