Skip to content
死亡复活

死亡复活

闯关小游戏需要一个角色死亡的条件,在该游戏中,当角色触碰到地面(Ground)即为死亡。本节课我们将通过学习触发器来制作死亡与复活的相关功能。

1.布置死亡区域

使用触发器来完成对关卡地面区域的覆盖,这片区域即为死亡区域。

选择资源库下的功能对象分类

点击“游戏功能对象”

将触发器拖动到场景中

调整触发器的大小和位置,让其覆盖关卡地面

image-20230828103710946

2.GameStart脚本

接下来我们需要编写代码了,在这里以GameStart脚本为例,给大家介绍一下如何创建脚本,以及了解脚本的运行逻辑。

创建脚本

①在工程内容中选择“脚本”

②点击“新建脚本”按钮

③将脚本名称修改为“GameStart”(这个命名可以是任意值,GameStart只是用作示例)

④将脚本拖动到挂载到场景中(挂载到场景上的脚本才会执行逻辑,后面会讲)

image-20230828105158682

脚本的默认结构

新建一个脚本,编辑器会默认向脚本中添加如下内容:

①class装饰器(没有这个装饰器,属性同步将不会生效)

②Script类(只有继承了这个类的脚本,才能够执行脚本的生命周期函数

③onStart函数(当脚本被挂载到场景上的时候,onStart会在游戏启动后自动执行)

④onUpdate函数(周期函数,每帧执行,前提是将this.useUpdate赋值为true)

⑤onDestroy函数(脚本被销毁时最后一帧执行完调用此函数)

image-20230828112215010

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必须手动替换为自己的,否则触发器将不会生效)

image-20231031101815584

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秒后,角色会复活在起点。