[开发者心得] 【事件通信】事件通信的应用场景

[复制链接]
1286 |1
空伊伊 发表于 2023-5-4 13:30:01 | 显示全部楼层 |阅读模式

本帖最后由 空伊伊 于 2023-11-8 16:52 编辑

事件通信的应用场景

目录

1.什么是事件通信?

2.本地通信的应用

案例1:脚本A通知脚本B执行逻辑

案例2:UI脚本通知脚本A执行逻辑

3.客户端和服务端通信的应用

案例1:客户端通知服务端存储数据

案例2:客户端向服务端请求数据

案例3:服务端向房间内所有客户端进行广播

4.使用事件通信的注意事项

1.什么是事件通信?

在口袋方舟中,如果你正确使用下列API进行逻辑处理,就是使用事件通信。

- 监听事件

  • Event.addLocalListener 本地监听(监听本地发送来的事件)
  • Event.addClientListener 客户端监听(监听客户端发送来的事件)
  • Event.addServerListener 服务端监听(监听服务端发送来的事件)
  • 派发事件
  • Events.dispatchToLocal 向本地发送事件
  • Events.dispatchToServer 向服务端发送事件
  • Events.dispatchToClient 向指定客户端发送事件
  • Events.dispatchToAllClient 向所有客户端发送事件

下方的视频展示了本节课的内容:(注:视频是旧版本录制的,视频中出现的代码是旧的,最新代码以文档为准)

<video controls src="https://forum.ark.online/forum.php?mod=attachment&aid=MjE4OXw3MWVkZjI4NnwxNjk2OTI0NjIxfDExM3wxNTcx&noupdate=yes"></video>

2.本地通信的应用

当脚本A和脚本B在同一个客户端或服务端中运行时,它们之间需要进行交互。这时候,你可以使用本地通信来实现它们之间的数据传输和协作。

案例1:脚本A通知脚本B执行逻辑

这个案例很常用,脚本之间互相调用、互相传值都可以通过这个方式来进行

脚本B监听本地事件 MyEvent

@Component
export default class ScriptB extends Script {
    protected onStart(): void {
        // 监听本地事件"MyEvent"
        Event.addLocalListener("MyEvent", (value: string) => {
            // 收到事件时,把收到的值传给sayHellow并执行
            this.sayHellow(value)
        })
    }

    public sayHellow(otherName: string) {
        console.log("Hello" + otherName + "I am ScriptB")
    }
}

脚本A派发本地事件 MyEvent

@Component
export default class ScriptA extends Script {
    protected onStart(): void {
        // 延迟5秒(原因是,需要等事件接收方准备好再派发事件,才能保证事件发送成功)
        setTimeout(() => {
            // 派发"MyEvent"事件,参数为"ScriptA"
            Event.dispatchToLocal("MyEvent", "ScriptA")
        }, 5000);
    }
}

案例2:UI脚本通知脚本A执行逻辑

游戏开发过程中,经常出现这样的需求:点击按钮,然后某个脚本执行对应的逻辑,我们可以像下面这样做

在 GameStart 里监听事件 MyEvent2

@Component
export default class GameStart extends Script {
    protected onStart(): void {
        Event.addLocalListener("MyEvent2", () => {
            console.log("按钮被点击了")
        })
    }
}

在 DefaultUI 中 JumpBtn 的点击事件中派发事件 MyEvent2

//点击跳跃按钮,异步获取人物后执行跳跃
jumpBtn.onPressed.add(()=>{
    if (this.character) {
        this.character.jump();
    } else {
        Player.asyncGetLocalPlayer().then((player) => {
            this.character = player.character;
            //角色执行跳跃功能
            this.character.jump();
        });
    }
    // 派发事件“MyEvent2”
    Event.dispatchToLocal("MyEvent2")
})

3.客户端和服务端通信的应用

由于客户端和服务端之间不能直接调用,所以需要使用相互抛事件的方式来进行通信

案例1:客户端通知服务端存储数据

这个例子在数据存储中很常见,因为需要持久化存储的数据只能在服务端进行存储,所以客户端想要存储数据,就需要先将数据发送到服务端,然后服务端再把数据进行存储

服务端脚本通过监听SendData事件来接收客户端发送来的数据并进行存储

@Component
export default class ServerScript extends Script {

    protected onStart(): void {
        // 在服务端设置存储环境
        DataStorage.setTemporaryStorage(SystemUtil.isPIE)

        // 监听事件SendData,作用是将player发送来的数据data存储为玩家数据
        Event.addClientListener("SendData", (player: Player, data) => {
            DataStorage.asyncSetData("key_" + player.playerId, data)
        })
    }
}

客户端脚本在启动5秒后,将数据233666发送给服务端进行存储

@Component
export default class ClientScript extends Script {
    protected onStart(): void {
        // 延迟5秒
        setTimeout(() => {
            // 将233666这个数据通过SendData事件发送给服务端
            Event.dispatchToServer("SendData", 233666)
        }, 5000);
    }
}

案例2:客户端向服务端请求数据

接着上一点,我们需要存储数据,当然也需要获取数据。因为需要持久化存储的数据只能存放在服务端,所以客户端想要使用数据,就需要先通知服务端,然后服务端再把数据发送给客户端才行

服务端脚本通过监听ReqData事件来获取对应客户端的数据并发送给对应客户端

@Component
export default class ServerScript extends Script {

    protected onStart(): void {
        // 在服务端设置存储环境
        DataStorage.setTemporaryStorage(SystemUtil.isPIE)

        // 监听事件ReqData,作用是获取player的玩家数据,并发送给player
        Event.addClientListener("ReqData", async (player: Player) => {
            // 获取player的数据
            let result = await DataStorage.asyncGetData("key_" + player.playerId)
            // 如果数据存在
            if (result.data) {
                // 将数据data通过GetData事件发送给客户端player
                Event.dispatchToClient(player, "GetData", esult.data)
            }
        })

    }
}

客户端脚本在启动5秒后向服务端请求数据,并将请求到的数据进行打印

@Component
export default class ClientScript extends Script {
    protected onStart(): void {

        // 客户端启动5秒后
        setTimeout(() => {
            // 向服务端发送事件ReqData,以请求数据
            Event.dispatchToServer("ReqData")
        }, 5000);

        // 监听服务端事件GetData,作用是接收服务端发送过来的数据
        Event.addServerListener("GetData", (data) => {
            // 打印数据
            console.log(data)
        })
    }
}

案例3:服务端向房间内所有客户端进行广播

服务端脚本每隔3秒向房间内的所有客户端发送BroadCast事件,并传递一个0~100的随机数

@Component
export default class ServerScript extends Script {

    protected onStart(): void {
        // 每隔3秒
        setInterval(() => {
            // 向所有客户端发送BroadCast事件,同时传递一个0~100的随机数
            Event.dispatchToAllClient("BroadCast", Math.random() * 100)
        }, 3000)

    }
}

客户端监听BroadCast事件,并将接收到的值进行打印

@Component
export default class ClientScript extends Script {
    protected onStart(): void {
        Event.addServerListener("BroadCast", (value: string) => {
            console.log("服务端传来的随机数:" + value)
        })
    }
}

4.使用事件通信的注意事项

事件通信的应用.mp4

76.2 MB, 下载次数: 52

回复

使用道具 举报

汽汽汽汽水 发表于 2023-5-6 09:23:49 | 显示全部楼层
回复

使用道具 举报

热门版块
快速回复 返回顶部 返回列表