死亡复活
闯关小游戏需要一个角色死亡的条件,在该游戏中,当角色触碰到地面(Ground)即为死亡。本节课我们将通过学习触发器来制作死亡与复活的相关功能。
1.布置死亡区域
使用触发器来完成对关卡地面区域的覆盖,这片区域即为死亡区域。
①选择资源库下的功能对象分类
②点击“游戏功能对象”
③将触发器拖动到场景中
④调整触发器的大小和位置,让其覆盖关卡地面
2.GameStart脚本
接下来我们需要编写代码了,在这里以GameStart脚本为例,给大家介绍一下如何创建脚本,以及了解脚本的运行逻辑。
创建脚本
①在工程内容中选择“脚本”
②点击“新建脚本”按钮
③将脚本名称修改为“GameStart”(这个命名可以是任意值,GameStart只是用作示例)
④将脚本拖动到挂载到场景中(挂载到场景上的脚本才会执行逻辑,后面会讲)
脚本的默认结构
新建一个脚本,编辑器会默认向脚本中添加如下内容:
①class装饰器(没有这个装饰器,属性同步将不会生效)
②Script类(只有继承了这个类的脚本,才能够执行脚本的生命周期函数)
③onStart函数(当脚本被挂载到场景上的时候,onStart会在游戏启动后自动执行)
④onUpdate函数(周期函数,每帧执行,前提是将this.useUpdate赋值为true)
⑤onDestroy函数(脚本被销毁时最后一帧执行完调用此函数)
3.LevelManager脚本
我们前面向场景中布置了一个触发器,由于触发器是需要配合脚本进行使用的,所以接下来教大家编写代码来使用触发器。
在这里我们使用一个脚本来专门处理与游戏关卡有关的逻辑,可以称这个脚本为“关卡管理器”。
新建一个脚本(不用拖入场景),并将其命名为LevelManager,编写逻辑如下:
该脚本有如下几个要点:
① LevelManager使用了单例模式,因此这个脚本不需要挂载到场景中。这个脚本将会通过挂载到场景上的GameStart脚本来进行驱动。
② 提供了初始化函数init,这个函数进行了对触发器的查找,并给触发器添加了进入逻辑。
③ 通过控制角色布娃娃属性的开启或关闭来代表死亡与复活。
④ 复活位置即是场景上初生点的位置,我们可以从属性面板上获取这个值。
ts
/**
* 关卡管理器
*/
export class LevelManager {
// 单例模式
private static _instacne: LevelManager
public static get instance(): LevelManager {
if (LevelManager._instacne == null) {
LevelManager._instacne = new LevelManager()
}
return LevelManager._instacne
}
/**死亡触发器 */
private _deathTrigger: Trigger
/**复活位置 */
private _rebornPosition: Vector = new Vector(10, 0, 420)
public async init() {
this._deathTrigger = await GameObject.asyncFindGameObjectById("299CDDA6") as Trigger
this._deathTrigger.onEnter.add((other: GameObject) => {
// 当进入的物体是角色类型
if (other instanceof Character) {
// 让角色死亡
this.charDeath(other)
}
})
}
/**让角色死亡 */
public charDeath(char: Character) {
// 开启布娃娃属性
char.ragdollEnabled = true
setTimeout(() => {
// 让角色复活
this.charReborn(char)
}, 3000);
}
/**让角色复活 */
public charReborn(char: Character) {
// 将角色的位置改变到复活点
char.worldTransform.position = this._rebornPosition.clone()
// 关闭布娃娃属性
char.ragdollEnabled = false
}
}
/**
* 关卡管理器
*/
export class LevelManager {
// 单例模式
private static _instacne: LevelManager
public static get instance(): LevelManager {
if (LevelManager._instacne == null) {
LevelManager._instacne = new LevelManager()
}
return LevelManager._instacne
}
/**死亡触发器 */
private _deathTrigger: Trigger
/**复活位置 */
private _rebornPosition: Vector = new Vector(10, 0, 420)
public async init() {
this._deathTrigger = await GameObject.asyncFindGameObjectById("299CDDA6") as Trigger
this._deathTrigger.onEnter.add((other: GameObject) => {
// 当进入的物体是角色类型
if (other instanceof Character) {
// 让角色死亡
this.charDeath(other)
}
})
}
/**让角色死亡 */
public charDeath(char: Character) {
// 开启布娃娃属性
char.ragdollEnabled = true
setTimeout(() => {
// 让角色复活
this.charReborn(char)
}, 3000);
}
/**让角色复活 */
public charReborn(char: Character) {
// 将角色的位置改变到复活点
char.worldTransform.position = this._rebornPosition.clone()
// 关闭布娃娃属性
char.ragdollEnabled = false
}
}
提示
上述代码中"299CDDA6"这串字符,它是我铺设在场景上的触发器的 GameObjectID
(场景上的每一个物体都有一个唯一的对象ID(即 GameObjectID)。我们可以通过选中物体,然后右键,在弹出的选项里点击“复制对象ID”即可完成复制)
(注意:这个GameObjectID必须手动替换为自己的,否则触发器将不会生效)
4.功能测试
功能测试之前,还需要对GameStart脚本进行一下改写,让其对LevelManager进行初始化。
GameStart脚本:
ts
import { LevelManager } from "./LevelManager";
@Component
export default class GameStart extends Script {
/** 当脚本被实例后,会在第一帧更新前调用此函数 */
protected async onStart(): Promise<void> {
if (SystemUtil.isClient()) {
LevelManager.instance.init()
}
}
/**
* 周期函数 每帧执行
* 此函数执行需要将this.useUpdate赋值为true
* @param dt 当前帧与上一帧的延迟 / 秒
*/
protected onUpdate(dt: number): void {
}
/** 脚本被销毁时最后一帧执行完调用此函数 */
protected onDestroy(): void {
}
}
import { LevelManager } from "./LevelManager";
@Component
export default class GameStart extends Script {
/** 当脚本被实例后,会在第一帧更新前调用此函数 */
protected async onStart(): Promise<void> {
if (SystemUtil.isClient()) {
LevelManager.instance.init()
}
}
/**
* 周期函数 每帧执行
* 此函数执行需要将this.useUpdate赋值为true
* @param dt 当前帧与上一帧的延迟 / 秒
*/
protected onUpdate(dt: number): void {
}
/** 脚本被销毁时最后一帧执行完调用此函数 */
protected onDestroy(): void {
}
}
启动游戏后,操控角色进入地面,角色就会切换到布娃娃模式,延迟3秒后,角色会复活在起点。