Skip to content
InputUtil

输入 / InputUtil

InputUtil Class

输入事件工具

使用示例:创建一个名为"InputExample"的脚本,放置在对象栏中,打开脚本,输入以下代码保存,运行游戏,点击键盘1键及屏幕,你将看到Input相关效果。代码如下:
ts
@Component
export default class InputExample extends Script {
    protected onStart(): void {
        InputUtil.onKeyDown(Keys.One, () => {
            console.error(`===>onKeyDown: Keys.One`);
        });
        InputUtil.onKeyUp(Keys.One, () => {
            console.error(`===>onKeyUp: Keys.One`);
        });
        InputUtil.onKeyPress(Keys.One, () => {
            console.error(`===>onKeyPress: Keys.One`);
        });
        InputUtil.onTouch((index: number, location: Vector2, touchType: TouchInputType) => {
            console.error(`===>onTouch: ${index}, ${location}, ${touchType}`);
        });
        InputUtil.onTouchBegin((index: number, location: Vector2, touchType: TouchInputType) => {
            console.error(`===>onTouchBegin: ${index}, ${location}, ${touchType}`);
        });
        InputUtil.onTouchMove((index: number, location: Vector2, touchType: TouchInputType) => {
            console.error(`===>onTouchMove: ${index}, ${location}, ${touchType}`);
        });
        InputUtil.onTouchEnd((index: number, location: Vector2, touchType: TouchInputType) => {
            console.error(`===>onTouchEnd: ${index}, ${location}, ${touchType}`);
        });
    }
}
@Component
export default class InputExample extends Script {
    protected onStart(): void {
        InputUtil.onKeyDown(Keys.One, () => {
            console.error(`===>onKeyDown: Keys.One`);
        });
        InputUtil.onKeyUp(Keys.One, () => {
            console.error(`===>onKeyUp: Keys.One`);
        });
        InputUtil.onKeyPress(Keys.One, () => {
            console.error(`===>onKeyPress: Keys.One`);
        });
        InputUtil.onTouch((index: number, location: Vector2, touchType: TouchInputType) => {
            console.error(`===>onTouch: ${index}, ${location}, ${touchType}`);
        });
        InputUtil.onTouchBegin((index: number, location: Vector2, touchType: TouchInputType) => {
            console.error(`===>onTouchBegin: ${index}, ${location}, ${touchType}`);
        });
        InputUtil.onTouchMove((index: number, location: Vector2, touchType: TouchInputType) => {
            console.error(`===>onTouchMove: ${index}, ${location}, ${touchType}`);
        });
        InputUtil.onTouchEnd((index: number, location: Vector2, touchType: TouchInputType) => {
            console.error(`===>onTouchEnd: ${index}, ${location}, ${touchType}`);
        });
    }
}

Table of contents

Accessors

isCursorInteractiveWithUI(): boolean client
获取鼠标指针是否能与 UI 交互
isCursorLockEnabled(): boolean client
获取是否允许通过快捷方式切换鼠标的使用组合模式
isCursorLocked(): boolean client
获取鼠标指针是否锁定
isCursorVisible(): boolean client
获取鼠标指针是否可见
isLockMouse(): boolean client
设置鼠标指针是否可以自由移动或是被锁定
mouseLockOptionEnabled(): boolean client
玩家是否可以使用shift,切换鼠标锁定状态

Methods

convertScreenLocationToWorldSpace(screenX: number, screenY: number): ConvertScreenResult
将二维屏幕位置转换为世界空间三维位置和方向
onKeyDown(Key: Keys, listener: () => void): EventListener
键盘输入事件-点击
onKeyPress(Key: Keys, listener: () => void): EventListener
键盘输入事件-按压
onKeyUp(Key: Keys, listener: () => void): EventListener
键盘输入事件-抬起
onRawTouchBegin(): MulticastDelegate<(FingerIndex: number, Position: Vector2) => void> client
获取手指按下代理,不被UI等影响的输入事件
onRawTouchEnd(): MulticastDelegate<(FingerIndex: number) => void> client
获取手指抬起代理,不被UI等影响的输入事件
onRawTouchMove(): MulticastDelegate<(FingerIndex: number, Position: Vector2) => void> client
获取手指滑动代理,不被UI等影响的输入事件
onTouch(listener: (index: number, location: Vector2, touchType: TouchInputType) => void): EventListener client
触摸事件
onTouchBegin(listener: (index: number, location: Vector2, touchType: TouchInputType) => void): EventListener client
触摸开始事件
onTouchEnd(listener: (index: number, location: Vector2, touchType: TouchInputType) => void): EventListener client
触摸结束事件
onTouchMove(listener: (index: number, location: Vector2, touchType: TouchInputType) => void): EventListener client
触摸移动事件
projectWorldPositionToWidgetPosition(worldLocation: Vector, playerViewportRelative?: boolean): ConvertScreenResult
获取角色在世界中的位置,投射到屏幕上

Accessors


isCursorInteractiveWithUI

Static get isCursorInteractiveWithUI(): boolean client

Static set isCursorInteractiveWithUI(canInteract): void client

获取鼠标指针是否能与 UI 交互

Returns

boolean是否能与 UI 交互

设置鼠标指针是否能与UI交互

Parameters

canInteract boolean可交互
使用示例:创建一个名为InputExample的脚本,放置在对象栏中,打开脚本,将原本内容修改为如下内容,保存并运行游戏,按下F键,可以切换鼠标是否可与屏幕UI交互,不可交互时,点击跳跃按钮无效
ts
@Component
export default class InputExample extends Script {

    protected onStart(): void {
        if (!SystemUtil.isClient()) return;
        this.test();
    }

    private async test(): `Promise`<`void`\> {
        //按下F键,修改鼠标是否可与屏幕UI交互
        InputUtil.onKeyDown(Keys.F, () => {
            InputUtil.enableCursorInteractWithUI = !InputUtil.isCursorInteractiveWithUI;
        })
    }

}
@Component
export default class InputExample extends Script {

    protected onStart(): void {
        if (!SystemUtil.isClient()) return;
        this.test();
    }

    private async test(): `Promise`<`void`\> {
        //按下F键,修改鼠标是否可与屏幕UI交互
        InputUtil.onKeyDown(Keys.F, () => {
            InputUtil.enableCursorInteractWithUI = !InputUtil.isCursorInteractiveWithUI;
        })
    }

}
使用示例:创建一个名为InputExample的脚本,放置在对象栏中,打开脚本,将原本内容修改为如下内容,保存并运行游戏,按下F键,可以切换鼠标是否可与屏幕UI交互,不可交互时,点击跳跃按钮无效
ts
@Component
export default class InputExample extends Script {

    protected onStart(): void {
        if (!SystemUtil.isClient()) return;
        this.test();
    }

    private async test(): `Promise`<`void`\> {
        //按下F键,修改鼠标是否可与屏幕UI交互
        InputUtil.onKeyDown(Keys.F, () => {
            InputUtil.enableCursorInteractWithUI(!InputUtil.isCursorInteractiveWithUI());
        })
    }

}
@Component
export default class InputExample extends Script {

    protected onStart(): void {
        if (!SystemUtil.isClient()) return;
        this.test();
    }

    private async test(): `Promise`<`void`\> {
        //按下F键,修改鼠标是否可与屏幕UI交互
        InputUtil.onKeyDown(Keys.F, () => {
            InputUtil.enableCursorInteractWithUI(!InputUtil.isCursorInteractiveWithUI());
        })
    }

}

isCursorLockEnabled

Static get isCursorLockEnabled(): boolean client

Static set isCursorLockEnabled(isEnableMouseLock): void client

获取是否允许通过快捷方式切换鼠标的使用组合模式

Returns

boolean是否可切换

设置是开启光标锁功能,开启后可以按shift键切换光标是否显示。

Parameters

isEnableMouseLock boolean是否开始shift键功能,此函数不会直接设置鼠标状态
使用示例:创建一个名为InputExample的脚本,放置在对象栏中,打开脚本,将原本内容修改为如下内容,保存并运行游戏,按下F键,可以切换shift键是否可以控制光标显示
ts
@Component
export default class InputExample extends Script {

    protected onStart(): void {
        if (!SystemUtil.isClient()) return;
        this.test();
    }

    private async test(): `Promise`<`void`\> {
        //按下F键,修改shift是否可控制光标显示
        InputUtil.onKeyDown(Keys.F, () => {
            InputUtil.enableCursorLock(!InputUtil.isCursorLockEnabled());
        })
    }

}
@Component
export default class InputExample extends Script {

    protected onStart(): void {
        if (!SystemUtil.isClient()) return;
        this.test();
    }

    private async test(): `Promise`<`void`\> {
        //按下F键,修改shift是否可控制光标显示
        InputUtil.onKeyDown(Keys.F, () => {
            InputUtil.enableCursorLock(!InputUtil.isCursorLockEnabled());
        })
    }

}
使用示例:创建一个名为InputExample的脚本,放置在对象栏中,打开脚本,将原本内容修改为如下内容,保存并运行游戏,按下F键,可以切换shift键是否可以控制光标显示
ts
@Component
export default class InputExample extends Script {

    protected onStart(): void {
        if (!SystemUtil.isClient()) return;
        this.test();
    }

    private async test(): `Promise`<`void`\> {
        //按下F键,修改shift是否可控制光标显示
        InputUtil.onKeyDown(Keys.F, () => {
            InputUtil.enableCursorLock = !InputUtil.isCursorLockEnabled;
        })
    }

}
@Component
export default class InputExample extends Script {

    protected onStart(): void {
        if (!SystemUtil.isClient()) return;
        this.test();
    }

    private async test(): `Promise`<`void`\> {
        //按下F键,修改shift是否可控制光标显示
        InputUtil.onKeyDown(Keys.F, () => {
            InputUtil.enableCursorLock = !InputUtil.isCursorLockEnabled;
        })
    }

}

isCursorLocked

Static get isCursorLocked(): boolean client

Static set isCursorLocked(isLock): void client

获取鼠标指针是否锁定

Returns

boolean是否锁定

设置鼠标指针是否锁定

Parameters

isLock boolean是否锁定
使用示例:创建一个名为InputExample的脚本,放置在对象栏中,打开脚本,将原本内容修改为如下内容,保存并运行游戏,按下F键,可以切换鼠标是否锁定,锁定后鼠标不可出到游戏窗口外
ts
@Component
export default class InputExample extends Script {

    protected onStart(): void {
        if (!SystemUtil.isClient()) return;
        this.test();
    }

    private async test(): `Promise`<`void`\> {
        //按下F键,锁定/解锁鼠标
        InputUtil.onKeyDown(Keys.F, () => {
            InputUtil.setCursorLocked(!InputUtil.isCursorLocked());
        })
    }

}
@Component
export default class InputExample extends Script {

    protected onStart(): void {
        if (!SystemUtil.isClient()) return;
        this.test();
    }

    private async test(): `Promise`<`void`\> {
        //按下F键,锁定/解锁鼠标
        InputUtil.onKeyDown(Keys.F, () => {
            InputUtil.setCursorLocked(!InputUtil.isCursorLocked());
        })
    }

}
使用示例:创建一个名为InputExample的脚本,放置在对象栏中,打开脚本,将原本内容修改为如下内容,保存并运行游戏,按下F键,可以切换鼠标是否锁定,锁定后鼠标不可出到游戏窗口外
ts
@Component
export default class InputExample extends Script {

    protected onStart(): void {
        if (!SystemUtil.isClient()) return;
        this.test();
    }

    private async test(): `Promise`<`void`\> {
        //按下F键,锁定/解锁鼠标
        InputUtil.onKeyDown(Keys.F, () => {
            InputUtil.setCursorLocked = !InputUtil.isCursorLocked;
        })
    }

}
@Component
export default class InputExample extends Script {

    protected onStart(): void {
        if (!SystemUtil.isClient()) return;
        this.test();
    }

    private async test(): `Promise`<`void`\> {
        //按下F键,锁定/解锁鼠标
        InputUtil.onKeyDown(Keys.F, () => {
            InputUtil.setCursorLocked = !InputUtil.isCursorLocked;
        })
    }

}

isCursorVisible

Static get isCursorVisible(): boolean client

Static set isCursorVisible(isVisible): void client

获取鼠标指针是否可见

Returns

boolean是否可见

设置鼠标指针是否可见

Parameters

isVisible boolean是否可见
使用示例:创建一个名为InputExample的脚本,放置在对象栏中,打开脚本,将原本内容修改为如下内容,保存并运行游戏,按下F键,可以切换鼠标是否可见
ts
@Component
export default class InputExample extends Script {

    protected onStart(): void {
        if (!SystemUtil.isClient()) return;
        this.test();
    }

    private async test(): `Promise`<`void`\> {
        //按下F键,显示/隐藏鼠标
        InputUtil.onKeyDown(Keys.F, () => {
            InputUtil.setCursorVisible(!InputUtil.isCursorVisible());
        })
    }

}
@Component
export default class InputExample extends Script {

    protected onStart(): void {
        if (!SystemUtil.isClient()) return;
        this.test();
    }

    private async test(): `Promise`<`void`\> {
        //按下F键,显示/隐藏鼠标
        InputUtil.onKeyDown(Keys.F, () => {
            InputUtil.setCursorVisible(!InputUtil.isCursorVisible());
        })
    }

}
使用示例:创建一个名为InputExample的脚本,放置在对象栏中,打开脚本,将原本内容修改为如下内容,保存并运行游戏,按下F键,可以切换鼠标是否可见
ts
@Component
export default class InputExample extends Script {

    protected onStart(): void {
        if (!SystemUtil.isClient()) return;
        this.test();
    }

    private async test(): `Promise`<`void`\> {
        //按下F键,显示/隐藏鼠标
        InputUtil.onKeyDown(Keys.F, () => {
            InputUtil.setCursorVisible = !InputUtil.isCursorVisible;
        })
    }

}
@Component
export default class InputExample extends Script {

    protected onStart(): void {
        if (!SystemUtil.isClient()) return;
        this.test();
    }

    private async test(): `Promise`<`void`\> {
        //按下F键,显示/隐藏鼠标
        InputUtil.onKeyDown(Keys.F, () => {
            InputUtil.setCursorVisible = !InputUtil.isCursorVisible;
        })
    }

}

isLockMouse

Static get isLockMouse(): boolean client

Static set isLockMouse(b): void client

设置鼠标指针是否可以自由移动或是被锁定

Returns

boolean鼠标指针是否可以自由移动或是被锁定

决定玩家的鼠标是否可以自由移动或是被锁定

Parameters

b booleanfalse 自由移动 true:锁定

mouseLockOptionEnabled

Static get mouseLockOptionEnabled(): boolean client

Static set mouseLockOptionEnabled(b): void client

玩家是否可以使用shift,切换鼠标锁定状态

Returns

boolean是否可以让玩家用shift切换鼠标状态

玩家是否可以使用shift,切换鼠标锁定状态

Parameters

b boolean如果为True,玩家在游戏中按下鼠标锁定按键(默认shift)后,玩家可以自行切换鼠标锁定状态
使用示例:创建一个名为InputExample的脚本,放置在对象栏中,打开脚本,将原本内容修改为如下内容,保存并运行游戏,按下F键,可以通过shift锁定鼠标,按下G键,不可以通过shift锁定鼠标
ts
@Component
export default class InputExample extends Script {

    protected onStart(): void {
        if (!SystemUtil.isClient()) return;
        this.test();
    }

    private async test(): `Promise`<`void`\> {
        //按下F键,可以通过shift锁定鼠标
        InputUtil.onKeyDown(Keys.F, () => {
            InputUtil.mouseLockOptionEnabled = true;
        })
        //按下G键,不可以通过shift锁定鼠标
        InputUtil.onKeyDown(Keys.G, () => {
            InputUtil.mouseLockOptionEnabled = false;
        })
    }
}
@Component
export default class InputExample extends Script {

    protected onStart(): void {
        if (!SystemUtil.isClient()) return;
        this.test();
    }

    private async test(): `Promise`<`void`\> {
        //按下F键,可以通过shift锁定鼠标
        InputUtil.onKeyDown(Keys.F, () => {
            InputUtil.mouseLockOptionEnabled = true;
        })
        //按下G键,不可以通过shift锁定鼠标
        InputUtil.onKeyDown(Keys.G, () => {
            InputUtil.mouseLockOptionEnabled = false;
        })
    }
}

Methods


convertScreenLocationToWorldSpace

Static convertScreenLocationToWorldSpace(screenX, screenY): ConvertScreenResult

将二维屏幕位置转换为世界空间三维位置和方向

Parameters

screenX number屏幕 X 轴坐标值 default:null range:不超过屏幕坐标,关于屏幕坐标详情请看 class Vector2 type: 浮点数
screenY number屏幕 Y 轴坐标值 default:null range:不超过屏幕坐标,关于屏幕坐标详情请看 class Vector2 type: 浮点数

Returns

ConvertScreenResult屏幕坐标转换结果
使用示例:创建一个名为InputExample的脚本,放置在对象栏中,打开脚本,将原本内容修改为如下内容,保存并运行游戏,按下 F 键,可以在屏幕中心位置发出一条射线,射线方向为屏幕中心位置指向屏幕外1000米处
ts
@Component
export default class InputExample extends Script {

    protected onStart(): void {
        if (!SystemUtil.isClient()) return;
        this.test();
    }

    private async test(): `Promise`<`void`\> {
        InputUtil.onKeyDown(Keys.F, () => {
            const result = InputUtil.convertScreenLocationToWorldSpace(960, 540);
            const startLoc = result.worldPosition;
            const dir = result.worldDirection;
            const endLoc = Vector.add(startLoc, dir.multiply(1000));
            mw.QueryUtil.lineTrace(startLoc, endLoc, true, true);
        })
    }

}
@Component
export default class InputExample extends Script {

    protected onStart(): void {
        if (!SystemUtil.isClient()) return;
        this.test();
    }

    private async test(): `Promise`<`void`\> {
        InputUtil.onKeyDown(Keys.F, () => {
            const result = InputUtil.convertScreenLocationToWorldSpace(960, 540);
            const startLoc = result.worldPosition;
            const dir = result.worldDirection;
            const endLoc = Vector.add(startLoc, dir.multiply(1000));
            mw.QueryUtil.lineTrace(startLoc, endLoc, true, true);
        })
    }

}

onKeyDown

Static onKeyDown(Key, listener): EventListener

键盘输入事件-点击

Parameters

Key Keys按键值
listener () => void监听回调

Returns

EventListener返回一个事件监听器
使用示例:创建一个名为InputExample的脚本,放置在对象栏中,打开脚本,将原本内容修改为如下内容,保存并运行游戏,日志会输出F键是否被按下的情况
ts
@Component
export default class InputExample extends Script {

    protected onStart(): void {
        if (!SystemUtil.isClient()) return;
        this.test();
    }

    private async test(): `Promise`<`void`\> {
        InputUtil.onKeyDown(Keys.F, () => {
            console.log("F key pressed");
        })
    }

}
@Component
export default class InputExample extends Script {

    protected onStart(): void {
        if (!SystemUtil.isClient()) return;
        this.test();
    }

    private async test(): `Promise`<`void`\> {
        InputUtil.onKeyDown(Keys.F, () => {
            console.log("F key pressed");
        })
    }

}

onKeyPress

Static onKeyPress(Key, listener): EventListener

键盘输入事件-按压

Parameters

Key Keys按键值
listener () => void监听回调

Returns

EventListener返回一个事件监听器
使用示例:创建一个名为InputExample的脚本,放置在对象栏中,打开脚本,将原本内容修改为如下内容,保存并运行游戏,日志会输出F键是否被按压的情况
ts
@Component
export default class InputExample extends Script {

    protected onStart(): void {
        if (!SystemUtil.isClient()) return;
        this.test();
    }

    private async test(): `Promise`<`void`\> {
        InputUtil.onKeyPress(Keys.F, () => {
            console.log("F key up");
        })
    }
}
@Component
export default class InputExample extends Script {

    protected onStart(): void {
        if (!SystemUtil.isClient()) return;
        this.test();
    }

    private async test(): `Promise`<`void`\> {
        InputUtil.onKeyPress(Keys.F, () => {
            console.log("F key up");
        })
    }
}

onKeyUp

Static onKeyUp(Key, listener): EventListener

键盘输入事件-抬起

Parameters

Key Keys按键值
listener () => void监听回调

Returns

EventListener返回一个事件监听器
使用示例:创建一个名为InputExample的脚本,放置在对象栏中,打开脚本,将原本内容修改为如下内容,保存并运行游戏,日志会输出F键是否被抬起的情况
ts
@Component
export default class InputExample extends Script {

    protected onStart(): void {
        if (!SystemUtil.isClient()) return;
        this.test();
    }

    private async test(): `Promise`<`void`\> {
        InputUtil.onKeyUp(Keys.F, () => {
            console.log("F key up");
        })
    }

}
@Component
export default class InputExample extends Script {

    protected onStart(): void {
        if (!SystemUtil.isClient()) return;
        this.test();
    }

    private async test(): `Promise`<`void`\> {
        InputUtil.onKeyUp(Keys.F, () => {
            console.log("F key up");
        })
    }

}

onRawTouchBegin

Static onRawTouchBegin(): MulticastDelegate<(FingerIndex: number, Position: Vector2) => void> client

获取手指按下代理,不被UI等影响的输入事件

Returns

MulticastDelegate<(FingerIndex: number, Position: Vector2) => void>返回手指按下时的代理

onRawTouchEnd

Static onRawTouchEnd(): MulticastDelegate<(FingerIndex: number) => void> client

获取手指抬起代理,不被UI等影响的输入事件

Returns

MulticastDelegate<(FingerIndex: number) => void>返回抬起手指时候的代理

onRawTouchMove

Static onRawTouchMove(): MulticastDelegate<(FingerIndex: number, Position: Vector2) => void> client

获取手指滑动代理,不被UI等影响的输入事件

Returns

MulticastDelegate<(FingerIndex: number, Position: Vector2) => void>返回手指滑动的代理

onTouch

Static onTouch(listener): EventListener client

触摸事件

Parameters

listener (index: number, location: Vector2, touchType: TouchInputType) => void监听回调

Returns

EventListener返回一个事件监听器

onTouchBegin

Static onTouchBegin(listener): EventListener client

触摸开始事件

Parameters

listener (index: number, location: Vector2, touchType: TouchInputType) => void监听回调

Returns

EventListener返回一个事件监听器

onTouchEnd

Static onTouchEnd(listener): EventListener client

触摸结束事件

Parameters

listener (index: number, location: Vector2, touchType: TouchInputType) => void监听回调

Returns

EventListener返回一个事件监听器

onTouchMove

Static onTouchMove(listener): EventListener client

触摸移动事件

Parameters

listener (index: number, location: Vector2, touchType: TouchInputType) => void监听回调

Returns

EventListener返回一个事件监听器

projectWorldPositionToWidgetPosition

Static projectWorldPositionToWidgetPosition(worldLocation, playerViewportRelative?): ConvertScreenResult

获取角色在世界中的位置,投射到屏幕上

Parameters

worldLocation Vector世界坐标
playerViewportRelative? boolean这是否应该相对于播放器视口子区域(在分割屏幕中使用播放器附加的小部件或纵横比受限时有用)default:false

Returns

ConvertScreenResult屏幕坐标转换结果,默认值为 Vector.ZERO
使用示例:创建一个名为InputExample的脚本,放置在对象栏中,打开脚本,将原本内容修改为如下内容,保存并运行游戏,按下F键,可以将按钮移动到玩家所在位置
ts
@Component
export default class InputExample extends Script {

    protected onStart(): void {
        if (!SystemUtil.isClient()) return;
        this.test();
    }

    private async test(): `Promise`<`void`\> {
        let btn = new ButtonUI();
        InputUtil.onKeyDown(Keys.F, async () => {
            let playerPos = Player.localPlayer.character.worldTransform.position;
            let result = InputUtil.projectWorldPositionToWidgetPosition(playerPos);
            if (result) {
                btn.button.position = result.screenPosition;
            }
        })
    }

}

class ButtonUI {
    public button: StaleButton;

    constructor(fun: Function = null) {
        this.creatUI(fun);
    }

    private creatUI(fun: Function = null) {
        // 创建一个UI对象
        let ui = UserWidget.newObject();
        // 将UI添加到屏幕上
        ui.addToViewport(1);
        // 创建一个画布组件
        let rootCanvas = Canvas.newObject();
        rootCanvas.size = new Vector2(1920, 1080);
        rootCanvas.position = Vector2.zero;
        // 将Ui的根画布设置为rootCanvas
        ui.rootContent = rootCanvas;
        // 创建一个按钮
        this.button = StaleButton.newObject(rootCanvas);
        this.button.position = new Vector2(1700, 310);
        this.button.size = new Vector2(150, 50);
        this.button.text = "按下变红";
        this.button.transitionEnable = true;
        this.button.pressedImagColor = LinearColor.red;
        this.button.visibility = SlateVisibility.Visible;

        this.button.onClicked.add(() => {
            if (fun) {
                fun();
            }
        })

    }
}
@Component
export default class InputExample extends Script {

    protected onStart(): void {
        if (!SystemUtil.isClient()) return;
        this.test();
    }

    private async test(): `Promise`<`void`\> {
        let btn = new ButtonUI();
        InputUtil.onKeyDown(Keys.F, async () => {
            let playerPos = Player.localPlayer.character.worldTransform.position;
            let result = InputUtil.projectWorldPositionToWidgetPosition(playerPos);
            if (result) {
                btn.button.position = result.screenPosition;
            }
        })
    }

}

class ButtonUI {
    public button: StaleButton;

    constructor(fun: Function = null) {
        this.creatUI(fun);
    }

    private creatUI(fun: Function = null) {
        // 创建一个UI对象
        let ui = UserWidget.newObject();
        // 将UI添加到屏幕上
        ui.addToViewport(1);
        // 创建一个画布组件
        let rootCanvas = Canvas.newObject();
        rootCanvas.size = new Vector2(1920, 1080);
        rootCanvas.position = Vector2.zero;
        // 将Ui的根画布设置为rootCanvas
        ui.rootContent = rootCanvas;
        // 创建一个按钮
        this.button = StaleButton.newObject(rootCanvas);
        this.button.position = new Vector2(1700, 310);
        this.button.size = new Vector2(150, 50);
        this.button.text = "按下变红";
        this.button.transitionEnable = true;
        this.button.pressedImagColor = LinearColor.red;
        this.button.visibility = SlateVisibility.Visible;

        this.button.onClicked.add(() => {
            if (fun) {
                fun();
            }
        })

    }
}