Skip to content
辅助功能

辅助功能

本节课将制作两个辅助功能,“复位”和“跳关”,这里对功能做一个简单介绍:

复位:能够让玩家操控的角色在被卡住或者穿模的情况下,快速回到上一个检查点位置

跳关:输入关卡序号即可跳转到指定关卡,方便我们对关卡进行测试

1.制作HelperUI

这两个辅助功能主要是通过UI来让玩家进行操控的,所以我们需要先制作UI。

创建HelperUI

点击工程内容下的“UI”

点击“新建UI”

将UI的名称修改为“HelperUI”

image-20230830102030254

拼UI并导出脚本

①拖入一个文本按钮控件,命名为mRest_btn,代表复位按钮

①拖入一个文本按钮控件,命名为mJump_btn,代表跳关按钮

①拖入一个输入框控件,命名为mJump_input,代表跳关输入框

②点击“导出所有脚本”

image-20230830102452382

2.编写HelperUI脚本

创建HelperUI脚本

①选择“UI”文件夹

②点击"新建脚本"

③将脚本的名字修改为HelperUI

image-20230830103140443

创建好之后,在HelperUI脚本里编写内容如下:

该脚本继承了HelperUI_Generate,所以脚本就能够控制HelperUI上的控件,在这里分别给复位按钮以及跳关按钮添加了点击事件,但是还没有编写具体的事件逻辑。

ts
import HelperUI_Generate from "../ui-generate/HelperUI_generate";

export class HelperUI extends HelperUI_Generate{
    protected onAwake(): void {

        // 复位功能
        this.mRest_btn.onClicked.add(()=>{

        })


        // 跳关功能
        this.mJump_btn.onClicked.add(()=>{

        })
    }
}
import HelperUI_Generate from "../ui-generate/HelperUI_generate";

export class HelperUI extends HelperUI_Generate{
    protected onAwake(): void {

        // 复位功能
        this.mRest_btn.onClicked.add(()=>{

        })


        // 跳关功能
        this.mJump_btn.onClicked.add(()=>{

        })
    }
}

有了HelperUI脚本后,我们就需要在游戏一开始通过UIService将HelperUI显示出来。

GameStart脚本中添加显示HelperUI的逻辑

ts
import { LevelManager } from "./LevelManager";
import { HelperUI } from "./UI/HelperUI";

@Component
export default class GameStart extends Script {

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

        if(SystemUtil.isClient()){
            LevelManager.instance.init()

            UIService.show(HelperUI);    
        }
    }
}
import { LevelManager } from "./LevelManager";
import { HelperUI } from "./UI/HelperUI";

@Component
export default class GameStart extends Script {

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

        if(SystemUtil.isClient()){
            LevelManager.instance.init()

            UIService.show(HelperUI);    
        }
    }
}

3.编写跳关函数

复位是返回到上一关,跳关是传送到指定关,所以这两个功能实际上只需要一个函数就能完成。

LevelManager脚本中添加跳关函数:

本次添加有如下几个要点:

添加了一个代表上一个检查点序号的成员变量lastPointNumber

在角色进入检查点的时候,更新lastPointNumber

编写jumpToPoint函数,该函数通过接收一个数字,然后根据数字去checkPointMap中获取检查点脚本,从而得到检查点,并将角色的位置设置到检查点位置从而完成了跳关功能。

jumpToPoint函数默认使用lastPointNumber,即不传入参数,函数会默认跳到上一关。

ts
import CheckPointTrigger from "./CheckPointTrigger"
import GameUI from "./UI/GameUI"

/**
 * 关卡管理器
 */
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 checkPointMap: Map<number, CheckPointTrigger> = new Map()

    /**上一个检查点的序号 */
    public lastPointNumber: number = 0

    public async init() {
        this._deathTrigger = await GameObject.asyncFindGameObjectById("299CDDA6") as Trigger
        this._deathTrigger.onEnter.add((other: GameObject) => {
            // 当进入的物体是角色类型
            if (other instanceof Character) {
                // 让角色死亡
                this.charDeath(other)
            }
        })


        Event.addLocalListener("CheckPoint", (checkPointTrigger: CheckPointTrigger) => {
            this._rebornPosition = checkPointTrigger.gameObject.worldTransform.position.clone()

            this.lastPointNumber = checkPointTrigger.pointNumber
        })

        setTimeout(() => {
            UIService.show(GameUI, this.checkPointMap.size, 0)
        }, 2000);
    }

    /**让角色死亡 */
    public charDeath(char: Character) {
        // 开启布娃娃属性
        char.ragdollEnabled = true
        // 播放特效
        EffectService.playAtPosition("27421", char.worldTransform.position)
        // 播放音效
        SoundService.playSound("120841")
        setTimeout(() => {
            // 让角色复活
            this.charReborn(char)
        }, 3000);

        if (char == Player.localPlayer.character) {
            Event.dispatchToLocal("Death")
        }
    }

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

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


    /** 
     * 跳转到指定关卡 
     * @param pointNumber 关卡号 
     */
    public jumpToPoint(pointNumber: number = this.lastPointNumber) {
        // 实现跳转 
        let checkPoint = this.checkPointMap.get(pointNumber)
        if (checkPoint) {
            Player.localPlayer.character.worldTransform.position = checkPoint.gameObject.worldTransform.position.clone()
        }
    }
}
import CheckPointTrigger from "./CheckPointTrigger"
import GameUI from "./UI/GameUI"

/**
 * 关卡管理器
 */
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 checkPointMap: Map<number, CheckPointTrigger> = new Map()

    /**上一个检查点的序号 */
    public lastPointNumber: number = 0

    public async init() {
        this._deathTrigger = await GameObject.asyncFindGameObjectById("299CDDA6") as Trigger
        this._deathTrigger.onEnter.add((other: GameObject) => {
            // 当进入的物体是角色类型
            if (other instanceof Character) {
                // 让角色死亡
                this.charDeath(other)
            }
        })


        Event.addLocalListener("CheckPoint", (checkPointTrigger: CheckPointTrigger) => {
            this._rebornPosition = checkPointTrigger.gameObject.worldTransform.position.clone()

            this.lastPointNumber = checkPointTrigger.pointNumber
        })

        setTimeout(() => {
            UIService.show(GameUI, this.checkPointMap.size, 0)
        }, 2000);
    }

    /**让角色死亡 */
    public charDeath(char: Character) {
        // 开启布娃娃属性
        char.ragdollEnabled = true
        // 播放特效
        EffectService.playAtPosition("27421", char.worldTransform.position)
        // 播放音效
        SoundService.playSound("120841")
        setTimeout(() => {
            // 让角色复活
            this.charReborn(char)
        }, 3000);

        if (char == Player.localPlayer.character) {
            Event.dispatchToLocal("Death")
        }
    }

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

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


    /** 
     * 跳转到指定关卡 
     * @param pointNumber 关卡号 
     */
    public jumpToPoint(pointNumber: number = this.lastPointNumber) {
        // 实现跳转 
        let checkPoint = this.checkPointMap.get(pointNumber)
        if (checkPoint) {
            Player.localPlayer.character.worldTransform.position = checkPoint.gameObject.worldTransform.position.clone()
        }
    }
}

4.完善HelperUI脚本逻辑

有了跳关功能,我们就需要给HelperUI上的按钮添加执行跳关功能的逻辑

编写HelperUI脚本逻辑如下:

ts
import { LevelManager } from "../LevelManager";
import HelperUI_Generate from "../ui-generate/HelperUI_generate";

export class HelperUI extends HelperUI_Generate{
    protected onAwake(): void {

        // 复位功能
        this.mRest_btn.onClicked.add(()=>{
            LevelManager.instance.jumpToPoint()
        })


        // 跳关功能
        this.mJump_btn.onClicked.add(()=>{
            LevelManager.instance.jumpToPoint( Number(this.mJump_input.text))
        })
    }
}
import { LevelManager } from "../LevelManager";
import HelperUI_Generate from "../ui-generate/HelperUI_generate";

export class HelperUI extends HelperUI_Generate{
    protected onAwake(): void {

        // 复位功能
        this.mRest_btn.onClicked.add(()=>{
            LevelManager.instance.jumpToPoint()
        })


        // 跳关功能
        this.mJump_btn.onClicked.add(()=>{
            LevelManager.instance.jumpToPoint( Number(this.mJump_input.text))
        })
    }
}

5.效果演示

20230830-105327