| 本帖最后由 脑的研发记录 于 2023-8-16 20:01 编辑 
 getUserId接口的排行榜翻新,附加隐藏显示按钮——用Replicated制作排行榜
 
 所用编辑器版本0.25.0.4
 工程附件在文末
 先上图
 
   总览:
 零,修改背景
 壹,一点思考想法
 贰,排行榜代码
 叁,相关推荐链接
 
 零,修改背景
 之前用的这位论坛师傅整的排行榜。
 【RPC和Replicated】—— 用Replicated制作排行榜 口袋方舟论坛|面向全年龄的UGC互动内容平台与交流社区 (ark.online)
 
 
 然后发现getPlayerID()会被维护掉会出现以下问题:
 击落广播功能——单脚本(含附件) 口袋方舟论坛|面向全年龄的UGC互动内容平台与交流社区 (ark.online)
 
 
   
 
 后来进行翻新,想法子解决问题,免得游戏更新了人还在上学没时间收拾,然后做了一点适配广播系统的修改,
 把客户端发送到服务端的通信改成了服务端到服务端的通信
 
 Events.dispatchToServer("reqAddScore", value)
 
 变成了
 
    Events.dispatchLocal("reqAddScore", killer, value)
 
 壹,一点思考想法
 
 1.把所有的number类型的playerID变成string类型,
 2.解决getplayer()需要number类型的playerID,
 于是就用map,不过由于这个排行榜和广播系统绑定了,
 map就不增加了,而是随用随从广播系统里Events.dispatchLocal("reqAddScore", killer, value)发送到这里
 
 
 不多说,上代码:
 
 贰,排行榜代码
 PS.老师傅的代码注释没有删去,鄙人用于自学理解的代码注释也混入其中,所以只讲与原排行榜不同的部分
 即进行修改的部分。
 附件的移植说明在最后有统一总结
 1.在新增了玩家名称变量:playerName
 ScoreSyncScript 脚本的代码改动:
 新增变量playerName,用@core装饰器,不启用回调onchanged
 
 import { RankMgr } from "./RankMgr";
 @Core.Class
 export default class ScoreSyncScript extends Core.Script {
 
 @Core.Property({ replicated: true, onChanged: "onPlayerChange" })
 public playerID: string = "";
 
 @Core.Property({ replicated: true, onChanged: "onScoreChange" })
 public score: number = -1;
 
 @Core.Property({ replicated: true })
 public playerName: string = "";
 //新增部分playerName,不onChanged回调函数,
 
 
 // /**初始化属性数据(如果同一帧触发了多个不同的onChanged函数,是不能保证其时序性的,所以我这里根据不同字段做了延迟操作,保证时序性) */
 public serverInit(playerID: string, playerName: string, score: number) {
 this.playerID = playerID
 this.playerName = playerName
 setTimeout(() => {
 // 同步分数(因为同步分数的时候,会触发刷新逻辑,需要使用到UI和角色对象,所以要稍微慢一秒,等待角色和UI初始化完毕)
 this.score = score
 
 }, 1000);
 }
 
 
 
 2.由于Wts My Name 更新玩家名称需要两秒,于是通过获取玩家名称来赋值的脚本就得延时,这里延时为3秒
 RankMgr脚本部分的初始化代码改动:
 1.player.getPlayerID()统一替换为play.getUserId()
 2.script.serverInit()函数增加参数string,即存储player.character.characterName用
 PS.在上传的文件当中,demo额外加了几行,单独初始化了一个同步脚本,注释“这是针对本次点击按钮试验而额外添加的代码.......”,
 如果实际应用,去掉这四行代码,就可以在排行榜中不显示“游戏姬”及其相关分数。
 
 private registJoinedAndLeftListenerEvent() {
 // 服务端监听玩家进入/离开房间
 if (SystemUtil.isServer()) {
 // 玩家上线,创建一个分数同步脚本
 
 
 Core.Script.spawnScript(ScoreSyncScript).then((script) => {
 script.serverInit("游戏姬", "游戏姬", 0)
 this.scoreSyncScriptList.push(script);
 })
 // 这是针对本次点击按钮试验而额外添加的代码,在真实使用中,这上面四行代码注释掉即可。
 
 
 Events.addPlayerJoinedListener(async (player: Gameplay.Player) => {
 await Core.Script.spawnScript(ScoreSyncScript).then((script) => {
 // 初始化同步脚本,同时进行一次上线同步
 setTimeout(() => {
 script.serverInit(player.getUserId(), player.character.characterName, 0)
 // 必须延迟在命名之后
 this.scoreSyncScriptList.push(script);
 }, 3000);
 // 将同步脚本添加到列表中,方便管理
 })
 })
 // 玩家下线,将该玩家分数同步脚本移除
 Events.addPlayerLeftListener((player: Gameplay.Player) => {
 // 删除服务器的分数同步脚本
 this.deleteScriptByPlayerID(player.getUserId())
 // 告诉所有客户端,这个玩家下线了,需要删除他在客户端的分数同步脚本
 Events.dispatchToAllClient("DeleteScriptByPlayerID", player.getUserId())
 })
 }
 }
 
 
 3.替换RPC,变成addLocalListner,同时内部参数也变成如图所示的killer,value,这里是完成给攻击来源加分的功能。
 注意其中一行注释“通过遍历来找到伤害来源的同步脚本”这就是说,killer 实际上是UserID。所以使用的时候,传进去的是UserID而不是玩家昵称。
 
 /**注册RPC事件 */
 private registRPCEvent() {
 if (SystemUtil.isServer()) {
 // 监听客户端发来的增加分数请求
 Events.addLocalListener("reqAddScore", (killer: string, value: number) => {
 // 原位置是接受客户端的消息,现在变成接受服务器其他脚本的消息。
 for (let script of this.scoreSyncScriptList) {
 if (script.playerID == killer) {
 // 通过遍历id来找到伤害来源的同步脚本
 script.serverAddScore(value)
 }
 // console.log("manager" + this.scoreSyncScriptList.length)
 }
 
 })
 }
 
 if (SystemUtil.isClient()) {
 // 监听服务端发来的删除同步脚本请求
 Events.addServerListener("DeleteScriptByPlayerID", (playerID: string) => {
 this.deleteScriptByPlayerID(playerID)
 })
 }
 }
 
 
 RPC得改一对儿,把接收端处理了,再解决发送端,外部函数名不变,内部改成如图所示。这个函数会在“击落广播”的贰,战况收集代码块的最后部分出现,
 这个函数也基本上是服务器处理完其他系统之后使用,把处理得到的赋分结果给到排行榜系统进行加分。
 这个AddScore的killer实际上就是UserID,这个函数安插到服务器的其他系统的时候,记得第一个参数是UserID,第二个参数是加的分数,可以自己设定加几分。
 
 /**向服务端内部文件模块间请求增加分数 */
 public AddScore(killer: string, value: number) {
 Events.dispatchLocal("reqAddScore", killer, value)
 // 把客户端与服务器端通信变成服务器内部的文件之间的通信。
 }
 
 
 4.RankMgr的dataList中的PlayerID由number变成string
 而且dataList.push,放进去的不是PlayerID,而是之前scoreSyncScript新增的PlayName.
 
     public tellUIFresh() {// 申明一个列表,存储玩家的分数数据
 let dataList: { "playerID": string, "score": number }[] = []
 // 从分数同步脚本上获取数据(这个脚本是在本地的,所以可以随取随用,不用发RPC)
 for (let script of this.scoreSyncScriptList) {
 if (script) {
 dataList.push({ "playerID": script.playerName, "score": script.score })
 // console.log("mgr"+script.playerName)
 }
 
 }
 // 排序
 dataList.sort((a, b) => { return b.score - a.score })
 // 通知UI刷新
 Events.dispatchLocal("FreshByData", dataList)
 }
 
 3.RankItemUI的修改
 PS.Author是别人,鄙人只是适配修改,如对该文案有修改问题还请先联系在下,暂时缘此不打扰老师傅了
 由于dataList,的字符串成员存的是玩家名称,所以直接在RankItemUI脚本里更新mRank_txt,这个就是排行榜的每条玩家的名字
 
 /*
 * @Author: ao001.wu ao001.wu@appshahe.com
 * @Date: 2023-03-19 18:24:47
 * @LastEditors: ao001.wu ao001.wu@appshahe.com
 * @LastEditTime: 2023-03-20 11:32:47
 * @FilePath: \ReplicatedDemo\JavaScripts\UI\RankItemUI.ts
 * @Description:
 */
 import RankItemUI_Generate from "../../ui-generate/RankItemUI_generate"
 
 
 export class RankItemUI extends RankItemUI_Generate {
 
 /**根据数据刷新显示 */
 public async freshByData(index: number, playerID: string, score: number) {
 
 this.mRank_txt.text = (index + 1).toString()
 
 
 if (playerID) {
 this.mName_txt.text = playerID
 }
 this.mScore_txt.text = score.toString()
 }
 }
 
 
 4.显示隐藏按钮
 
 这个是做跑酷游戏的时候觉得还是有隐藏按钮视野开阔,打算在踩影子PVP中给加上显示隐藏按钮
 
 
 /**
 * AUTHOR: 脑的研发记录
 
 * TIME: 2023.08.12-18.31.34*/
 import rankClose_Generate from "../ui-generate/rankClose_generate";
 import { RankUI } from "./UI/RankUI";
 export default class rankbtn extends rankClose_Generate {
 
 /**
 * 构造UI文件成功后,在合适的时机最先初始化一次
 */
 protected onStart() {
 //设置能否每帧触发onUpdate
 this.canUpdate = false;
 this.layer = UI.UILayerMiddle;
 this.btn.text = "隐藏"
 let show :boolean = true;
 this.btn.onPressed.add(()=>{
 if(show){
 UI.UIManager.instance.hide(RankUI)
 show = false
 this.btn.text = "显示"
 }else {
 UI.UIManager.instance.show(RankUI)
 show = true;
 this.btn.text = "隐藏"
 }
 })
 }
 }
 
 
 
 附件与附件说明:
 
  广播与排行榜组合.zip
(123.67 KB, 下载次数: 475) |