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.使用触发器

我们前面向场景中布置了一个触发器,由于触发器是需要配合脚本进行使用的,所以接下来教大家编写代码来使用触发器。

GameStart脚本中编写如下逻辑:

脚本实现了查找到场景上的触发器,并且给触发器添加进入逻辑,现在触发器就能够实现:当有物体进入触发器区域,就会在日志窗口打印“有物体进入”。

ts
@Component
export default class GameStart extends Script {

    /** 当脚本被实例后,会在第一帧更新前调用此函数 */
    protected async onStart(): Promise<void> {

        console.log("脚本启动")

        // 查找触发器
        let trigger = await GameObject.asyncFindGameObjectById("299CDDA6") as Trigger
        // 给触发器添加进入逻辑
        trigger.onEnter.add((other: GameObject) => {
            console.log("有物体进入")
        })
    }

    /**
     * 周期函数 每帧执行
     * 此函数执行需要将this.useUpdate赋值为true
     * @param dt 当前帧与上一帧的延迟 / 秒
     */
    protected onUpdate(dt: number): void {

    }

    /** 脚本被销毁时最后一帧执行完调用此函数 */
    protected onDestroy(): void {

    }
}
@Component
export default class GameStart extends Script {

    /** 当脚本被实例后,会在第一帧更新前调用此函数 */
    protected async onStart(): Promise<void> {

        console.log("脚本启动")

        // 查找触发器
        let trigger = await GameObject.asyncFindGameObjectById("299CDDA6") as Trigger
        // 给触发器添加进入逻辑
        trigger.onEnter.add((other: GameObject) => {
            console.log("有物体进入")
        })
    }

    /**
     * 周期函数 每帧执行
     * 此函数执行需要将this.useUpdate赋值为true
     * @param dt 当前帧与上一帧的延迟 / 秒
     */
    protected onUpdate(dt: number): void {

    }

    /** 脚本被销毁时最后一帧执行完调用此函数 */
    protected onDestroy(): void {

    }
}

提示

上述代码中"299CDDA6"这串字符,它是我们铺设在场景上的触发器的 Guid

(场景上的每一个物体都有一个唯一的对象ID(即 Guid)。我们可以通过选中物体,然后右键,在弹出的选项里点击“复制对象ID”即可完成复制)

效果展示

运行游戏后,操控角色进入触发器区域,就会将“有物体进入”打印在日志窗口

MetaApp20230828-134603

4.LevelManager脚本

好的,你已经会使用触发器了,那么接下来让我们完成闯关小游戏的第一个核心逻辑吧。

在这里我们使用一个脚本来专门处理与游戏关卡有关的逻辑,可以称这个脚本为“关卡管理器”。

新建一个脚本,并将其命名为LevelManager,编写逻辑如下:

该脚本有如下几个要点:

LevelManager使用了单例模式,因此这个脚本不需要挂载到场景中。这个脚本将会通过挂载到场景上的GameStart脚本来进行驱动。

提供了一个初始化函数init,这个函数进行了对触发器的查找,并给触发器添加了进入逻辑。

通过控制角色布娃娃属性的开启或关闭来代表死亡与复活。

复活位置即是场景上初生点的位置,我们可以从属性面板上获取这个值。

typescript
/**
 * 关卡管理器
 */
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)
            }
        })
    }

    /**让角色死亡 */
    private charDeath(char:Character){
        // 开启布娃娃属性
        char.ragdollEnabled = true

        setTimeout(() => {
            // 让角色复活
            this.charReborn(char)
        }, 3000);
    }

    /**让角色复活 */
    private 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)
            }
        })
    }

    /**让角色死亡 */
    private charDeath(char:Character){
        // 开启布娃娃属性
        char.ragdollEnabled = true

        setTimeout(() => {
            // 让角色复活
            this.charReborn(char)
        }, 3000);
    }

    /**让角色复活 */
    private charReborn(char:Character){
        // 将角色的位置改变到复活点
        char.worldTransform.position = this._rebornPosition.clone()

        // 关闭布娃娃属性
        char.ragdollEnabled = false
    }
}

5.功能测试

功能测试之前,还需要对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秒后,角色会复活在起点。