# 框架开发
小游戏框架整体采用类ECS架构,开发者可以开发自定义component脚本,来操纵游戏实体(Entity),从而实现游戏逻辑。
# 创建Script Component脚本。
游戏的节点树由实体Entity组成,每一个Entity都可以挂载不同的组件Component,用于实现不同的能力。比如内置的MeshRenderer Component用于渲染。开发者也可以实现自己的脚本组件,继承于engine.Script。在脚本中定义组件的生命周期的回调函数,就可以去实现游戏逻辑,或是修改其他组件的属性。
开发者可以自己使用代码编辑器创建脚本,也可以通过小游戏工具的Project窗口右键新建 >> script来创建默认模版。文件名将会默认作为你的脚本组件的类名。右键这个脚本文件就可以选择使用内置编辑器,或是系统默认软件打开。
# 脚本组件的结构
新建的脚本一般如下,包含了一个类。每当被添加到一个Entity上面的时候都会生成这个类新的实例。
import engine from "engine";
@engine.decorators.serialize("Move")
export default class Move extends engine.Script {
@engine.decorators.property({
type: 'string'
})
public name: string = "myname"
public onAwake() {
}
public onUpdate(dt) {
}
public onDestroy() {
}
}
这个类有几部分组成。
- 脚本组件是一个继承于engine.Script的类,engine.Script本身继承于engine.Component。
- 对于这个类有一个serialize装饰器,是用标示这个类型是一个可序列化的类。装饰器的入参应该保证是一个唯一值。
- 对于属性可以使用property装饰器来标示,可以用于序列化落地以及UI可视化,具体可以在后面序列化系统章节中查看。
- onAwake/onUpdate等生命周期,这些注册的回调会在组件生命周期被执行,用于开发游戏逻辑。比如onUpdate就是在游戏每一帧调用的,可以用来实现位置移动等能力。生命周期具体有哪些,可以在后面的生命周期章节中查看。
# 添加到Entity上
有两种方式将你的脚本添加到Entity上。
在编辑态添加。在Project窗口中,拖动一个脚本组件文件到Hierarchy窗口的对应entity上即可绑定。或是打开编辑一个Scene或是Prefab,选中Hierarchy的对应Entity,然后在inspector中最下面可以点击添加组件。除了内置的组件外,还有Script分类,开发者可以找到添加刚刚自己创建的脚本名称,名称是serialize装饰器的名称。添加到Entity后保存Scene或Prefab,序列化系统会把属性当前的值也保存进去,这样后续就不需要每次动态添加。
在脚本运行的时候添加。开发者可以使用entity.addComponent(Move)来动态按需添加一个组件。
# 获取与修改属性
组件中在回调函数里面可以使用this.entity来获取当前的Entity,并且可以直接对它进行修改。也可以通过getComponent来获取其他组件。
public onUpdate(dt) {
// 改变3D节点位置
this.entity.transform.position.x++
// 获取其他组件
const mr = this.entity.getComponent(engine.MeshRenderer)
}
# 2D/3D 事件通信
小游戏框架将Scene和Prefab区分为2D和3D两种,但是很多情况下两者需要互相调用通信,比如使用2D的操纵杆来移动3D的人物。小游戏框架内部提供了事件系统engine.game.customEventEmitter来实现通信。
// 3D组件
onAwake() {
engine.game.customEventEmitter.on('TOUCH_MOVE', (direction) => {
...
});
}
// 2D组件
onTouchMove() {
engine.game.customEventEmitter.emit('TOUCH_MOVE', direction)
}
# 生命周期
组件以及框架本身有对应的生命周期可以使用,比如onAwake,onUpdate等。可以查看生命周期章节查看