参考资料
核心概述
Cocos Creator 是一款轻量级、跨平台的 2D/3D 游戏开发引擎,其核心设计理念是 数据驱动 + 组件化 + 场景化
引擎全面拥抱 TypeScript 作为主要脚本语言,通过静态类型检查和丰富的语法特性,帮助开发者编写更健壮、可维护的代码
可以自定义脚本编辑器、预览浏览器
节点与组件系统
节点(Node) 是 Cocos Creator 中的基本单位,可以是角色、道具、背景等各种游戏元素。节点通过父子关系构建复杂的场景结构,子节点的位置、旋转等属性是相对于父节点的。
组件(Component) 是附加在节点上的模块化代码片段,用于赋予节点特定的功能和行为。一个节点可以包含多个组件,组件之间可以相互配合。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
flowchart LR
A[场景 Scene] --> B[根节点 Canvas]
B --> C[节点 Node 1]
B --> D[节点 Node 2]
C --> E[组件 Component A]
C --> F[组件 Component B]
D --> G[组件 Component C]
style A fill:#e3f2fd
style B fill:#bbdefb
style C fill:#90caf9
style D fill:#90caf9
style E fill:#64b5f6
style F fill:#64b5f6
style G fill:#64b5f6
|
生命周期回调详解
组件脚本继承自Component,引擎提供了完整的生命周期回调函数:
-
onLoad
会在脚本组件的 初始化阶段 被调用
总会在调用 start 方法前被执行,可以用于设置脚本的初始化顺序,或者做一些初始化相关的操作
-
onEnable
当组件的 enabled 属性从 false 变为 true
或者所在节点的 active 属性从 false 变为 true 时
都会激活 onEnable 回调函数
如果节点第一次被创建且 enabled 属性为 true,则调用顺序为:onLoad–onEnable–start
-
start
通常用于初始化一些 中间状态的数据
这些数据可能会在 update 时发生改变,并且被频繁地进行 enable 和 disable 操作
-
update
会在游戏 每一帧渲染之前 被触发
游戏开发的一个关键点是在每一帧渲染前更新物体的行为、状态和方位
这些更新操作通常都被放在 update 回调函数中
-
lateUpdate
会在游戏 每一帧渲染之后 被触发
用于在动效(如动画、粒子、物理等)更新之后进行 额外的操作
或者希望在执行完成所有组件的 update 之后进行其他操作
-
onDisable
当组件的 enabled 属性从 true 变为 false 时
或者所在节点的 active 属性从 true 变为 false 时
会激活 onDisable 回调函数
-
onDestroy
当组件或者所在节点调用了 destroy 函数时
回调函数 onDestroy 也会被调用
并在当前帧结束时统一 回收组件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
import { _decorator, Component } from "cc";
const { ccclass, property } = _decorator;
@ccclass("GameController")
export class GameController extends Component {
// 1. onLoad: 组件初始化阶段
onLoad() {
console.log("组件加载完成");
// 初始化游戏设置、加载资源等
}
// 2. onEnable: 组件启用时
onEnable() {
console.log("组件已启用");
// 注册事件监听器等
}
// 3. start: 首次update前
start() {
console.log("游戏开始");
// 初始化游戏状态
}
// 4. update: 每帧更新
update(deltaTime: number) {
// 更新游戏逻辑、状态、方位
// deltaTime: 与上一帧的时间间隔(秒)
}
// 5. lateUpdate: 每帧更新后
lateUpdate() {
// 处理动画、物理等更新后的操作
}
// 6. onDisable: 组件禁用时
onDisable() {
console.log("组件已禁用");
// 注销事件监听器等
}
// 7. onDestroy: 组件销毁时
onDestroy() {
console.log("组件即将销毁");
// 清理资源、释放引用等
}
}
|
执行顺序:
- 节点创建并激活时:
onLoad → onEnable → start → update → lateUpdate
- 组件禁用时:
onDisable
- 节点销毁时:
onDestroy
常用 API 与操作
节点操作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
// 创建节点
let newNode = new cc.Node("NewNode");
// 或者实例化预制体
let prefabNode = cc.instantiate(prefab);
// 添加子节点
this.node.addChild(newNode);
// 设置父节点
newNode.parent = this.node;
// 获取节点
let targetNode = cc.find("Canvas/TargetNode");
// 或者通过路径查找
let child = this.node.getChildByName("ChildName");
// 节点属性操作
newNode.setPosition(cc.v2(100, 100)); // 设置位置
newNode.setRotation(45); // 设置旋转角度
newNode.setScale(2); // 设置缩放比例
// 节点显隐控制
newNode.active = true; // 显示
newNode.active = false; // 隐藏
// 销毁节点
this.node.destroy();
|
场景与资源管理
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
// 场景切换
cc.director.loadScene("GameScene");
// 资源加载
// 加载单个资源
cc.resources.load("textures/player", cc.SpriteFrame, (err, spriteFrame) => {
if (err) {
console.error(err);
return;
}
// 使用资源
});
// 加载图集资源
cc.resources.load("atlas/game-atlas", cc.SpriteAtlas, (err, atlas) => {
if (err) {
console.error(err);
return;
}
const frame = atlas.getSpriteFrame("enemy-1");
});
// 资源释放
// 当不再使用资源时,应该释放以避免内存泄漏
this.spriteFrame.decRef();
|
UI 组件与交互
Cocos Creator 提供了丰富的 UI 组件,用于构建游戏界面:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
// 按钮交互
const { property, ccclass } = cc._decorator;
import { Button, Node } from "cc";
@ccclass("UIController")
export class UIController extends Component {
@property(Button)
private startButton: Button = null;
@property(Node)
private panelNode: Node = null;
onLoad() {
// 添加按钮点击事件
this.startButton.node.on(Button.EventType.CLICK, this.onStartGame, this);
// 添加触摸事件
this.panelNode.on(Node.EventType.TOUCH_START, this.onTouchStart, this);
}
onStartGame() {
console.log("游戏开始!");
// 切换场景、开始游戏逻辑等
}
onTouchStart(event: cc.Event.EventTouch) {
const touchPos = event.getLocation();
console.log(`触摸位置: (${touchPos.x}, ${touchPos.y})`);
}
onDestroy() {
// 记得注销事件监听
this.startButton.node.off(Button.EventType.CLICK, this.onStartGame, this);
this.panelNode.off(Node.EventType.TOUCH_START, this.onTouchStart, this);
}
}
|
实战技巧与最佳实践
建议的项目结构
1
2
3
4
5
6
7
8
9
10
11
|
assets/
├── scenes/ # 场景文件
├── scripts/ # TypeScript脚本
│ ├── controllers/ # 游戏控制器
│ ├── components/ # 可复用组件
│ ├── data/ # 数据模型
│ └── utils/ # 工具函数
├── resources/ # 需要动态加载的资源
├── textures/ # 图片资源
├── audio/ # 音频资源
└── prefabs/ # 预制体
|
TypeScript 工程化实践
- 使用严格模式:在
tsconfig.json中启用"strict": true,有助于捕获潜在错误
- 充分利用类型推断:减少冗余的类型注解,让代码更简洁
- 接口优先:使用接口定义数据结构,增强类型安全性
- 模块化设计:避免全局污染,使用命名空间和模块系统
性能优化建议
高级优化技巧
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
// 1. 对象池模式(避免频繁创建销毁)
class GameObjectPool {
private pool: cc.Node[] = [];
private prefab: cc.Prefab;
constructor(prefab: cc.Prefab) {
this.prefab = prefab;
}
public get(): cc.Node {
let node: cc.Node;
if (this.pool.length > 0) {
node = this.pool.pop()!;
} else {
node = cc.instantiate(this.prefab);
}
node.active = true;
return node;
}
public put(node: cc.Node): void {
node.active = false;
this.pool.push(node);
}
}
// 2. 批量更新(减少频繁的节点操作)
update(dt: number) {
// 收集所有需要更新的节点
const nodesToUpdate: cc.Node[] = [];
// 一次性处理
nodesToUpdate.forEach(node => {
node.setPosition(node.position.x + speed * dt, node.position.y);
});
}
// 3. 使用cc.SpriteFrame的缓存
const spriteFrameCache = new Map<string, cc.SpriteFrame>();
async function loadSpriteFrame(path: string): Promise<cc.SpriteFrame> {
if (spriteFrameCache.has(path)) {
return spriteFrameCache.get(path)!;
}
return new Promise((resolve) => {
cc.resources.load(path, cc.SpriteFrame, (err, spriteFrame) => {
if (!err) {
spriteFrameCache.set(path, spriteFrame);
resolve(spriteFrame);
}
});
});
}
|
学习路径与资源推荐
阶段性学习目标
| 阶段 |
目标 |
关键技术点 |
| 入门阶段 |
基础概念掌握 |
TypeScript 基础、节点操作、生命周期、简单 UI |
| 进阶阶段 |
游戏开发能力 |
组件通信、资源管理、动画系统、场景管理 |
| 实战阶段 |
完整项目开发 |
性能优化、发布打包、热更新、团队协作 |
实用开发技巧
-
编辑器快捷操作
- 使用
Ctrl+D复制节点
- 使用
Ctrl+Shift+F全局搜索
- 使用
F键聚焦选中节点
-
调试技巧
- 使用
console.log进行简单调试
- 使用 Chrome 开发者工具进行深度调试
- 使用
cc.debug进行性能监控
-
常见陷阱规避
- 避免在
update中频繁创建对象
- 及时释放不再使用的资源
- 正确处理节点销毁时的清理工作