排行榜
排行榜是游戏中最常见的一个功能,此功能已经内置在编辑器了,本节课就来教大家如何使用吧!
1.内置排行榜的构成
排行榜如下图所示(黑框框起来的部分):
①黄色框选部分:该部分为排行榜的标题,这个标题的文本可以自定义。
②红色框选部分:该部分为排行榜的字段,字段数量以及字段内容可以自行定义。
③蓝色框选部分:该部分为排行榜中的一条数据,排行榜会自动根据数据进行排序。
2.设置排行榜的样式
编辑器内置了一个排行榜模块,可以通过LeaderboardModule来调用到与之相关的各种功能。
我们首先需要设置排行榜的样式,设置样式的代码需要在客户端进行设置。所以我们来到GameStart脚本中添加相关代码:
视频教程修正
由于视频教程录制时的编辑器版本比较旧,所以视频中是在服务端设置了样式。
正确应该如下方文档所示,在客户端设置。
此次添加的主要内容:
①定义了一个枚举FieldType,用来表示所有的排行榜字段类型
②通过LeaderboardModule.setStyle设置了排行榜的标题内容以及字段间距
③通过LeaderboardModule.addField向排行榜添加自定义字段
④通过LeaderboardModule.showRankField向排行榜添加排名字段
ts
import { LevelData } from "./LevelData";
import { LevelManager } from "./LevelManager";
import { HelperUI } from "./UI/HelperUI";
/**所有的排行榜字段 */
export enum FieldType {
Name,
PointNumber
}
@Component
export default class GameStart extends Script {
/** 当脚本被实例后,会在第一帧更新前调用此函数 */
protected async onStart(): Promise<void> {
if (SystemUtil.isClient()) {
LevelManager.instance.init()
UIService.show(HelperUI);
// 在客户端设置排行榜的样式
LeaderboardModule.setStyle("排行榜", true, 10, 5)
// 设置排行榜的字段(玩家名称,关卡号)
LeaderboardModule.addField(FieldType.Name, "玩家名")
LeaderboardModule.addField(FieldType.PointNumber, "关卡号")
LeaderboardModule.showRankField("排名", null, "未上榜")
}
if (SystemUtil.isServer()) {
// 设置存储环境
DataStorage.setTemporaryStorage(SystemUtil.isPIE)
// 数据存储逻辑
Event.addClientListener("SavePoint", (player: Player, pointNumber: number) => {
// 使用数据中心存储数据
// 改变数据
DataCenterS.getData(player, LevelData).pointNumber = pointNumber
// 存储数据
DataCenterS.getData(player, LevelData).save(true)
})
}
}
}
import { LevelData } from "./LevelData";
import { LevelManager } from "./LevelManager";
import { HelperUI } from "./UI/HelperUI";
/**所有的排行榜字段 */
export enum FieldType {
Name,
PointNumber
}
@Component
export default class GameStart extends Script {
/** 当脚本被实例后,会在第一帧更新前调用此函数 */
protected async onStart(): Promise<void> {
if (SystemUtil.isClient()) {
LevelManager.instance.init()
UIService.show(HelperUI);
// 在客户端设置排行榜的样式
LeaderboardModule.setStyle("排行榜", true, 10, 5)
// 设置排行榜的字段(玩家名称,关卡号)
LeaderboardModule.addField(FieldType.Name, "玩家名")
LeaderboardModule.addField(FieldType.PointNumber, "关卡号")
LeaderboardModule.showRankField("排名", null, "未上榜")
}
if (SystemUtil.isServer()) {
// 设置存储环境
DataStorage.setTemporaryStorage(SystemUtil.isPIE)
// 数据存储逻辑
Event.addClientListener("SavePoint", (player: Player, pointNumber: number) => {
// 使用数据中心存储数据
// 改变数据
DataCenterS.getData(player, LevelData).pointNumber = pointNumber
// 存储数据
DataCenterS.getData(player, LevelData).save(true)
})
}
}
}
3.向排行榜 添加/删除/设置 数据
每当有玩家进入房间的时候,就需要向排行榜上添加一条数据;同时每当玩家通过新的检查点的时候,就需要更新排行榜上面的关卡号;最后,每当有玩家退出房间的时候,就需要将对应玩家的数据从排行榜上移除。
还是在GameStart脚本中添加逻辑:
此次添加的主要内容:
①在服务端使用Player.onPlayerJoin来监听玩家进入房间的事件,然后再调用LeaderboardModule.addPlayer来向排行榜上添加数据。
②在服务端使用Player.onPlayerLeave来监听玩家离开房间的事件,然后再调用LeaderboardModule.removePlayer来从排行榜上移除数据。
③在SavePoint事件触发的时候,通过LeaderboardModule.setPlayerValue设置字段数据。
ts
import { LevelData } from "./LevelData";
import { LevelManager } from "./LevelManager";
import GameUI from "./UI/GameUI";
import { HelperUI } from "./UI/HelperUI";
/**所有的排行榜字段 */
export enum FieldType {
Name,
PointNumber
}
@Component
export default class GameStart extends Script {
/** 当脚本被实例后,会在第一帧更新前调用此函数 */
protected async onStart(): Promise<void> {
if (SystemUtil.isClient()) {
LevelManager.instance.init()
UIService.show(HelperUI);
// 在客户端设置排行榜的样式
LeaderboardModule.setStyle("排行榜", true, 10, 5)
// 设置排行榜的字段(玩家名称,关卡号)
LeaderboardModule.addField(FieldType.Name, "玩家名")
LeaderboardModule.addField(FieldType.PointNumber, "关卡号")
LeaderboardModule.showRankField("排名", null, "未上榜")
}
if (SystemUtil.isServer()) {
// 设置存储环境
DataStorage.setTemporaryStorage(SystemUtil.isPIE)
// 数据存储逻辑
Event.addClientListener("SavePoint", (player: Player, pointNumber: number) => {
// 使用数据中心存储数据
// 改变数据
DataCenterS.getData(player, LevelData).pointNumber = pointNumber
// 存储数据
DataCenterS.getData(player, LevelData).save(true)
LeaderboardModule.setPlayerValue(player, FieldType.PointNumber, pointNumber)
LeaderboardModule.setPlayerValue(player, FieldType.Name, player.character.displayName)
})
// 当玩家进入游戏,向排行榜添加一条数据
Player.onPlayerJoin.add((player: Player) => {
LeaderboardModule.addPlayer(player)
})
// 当玩家退出游戏,将数据从排行榜上删除
Player.onPlayerLeave.add((player: Player) => {
LeaderboardModule.removePlayer(player)
})
}
}
}
import { LevelData } from "./LevelData";
import { LevelManager } from "./LevelManager";
import GameUI from "./UI/GameUI";
import { HelperUI } from "./UI/HelperUI";
/**所有的排行榜字段 */
export enum FieldType {
Name,
PointNumber
}
@Component
export default class GameStart extends Script {
/** 当脚本被实例后,会在第一帧更新前调用此函数 */
protected async onStart(): Promise<void> {
if (SystemUtil.isClient()) {
LevelManager.instance.init()
UIService.show(HelperUI);
// 在客户端设置排行榜的样式
LeaderboardModule.setStyle("排行榜", true, 10, 5)
// 设置排行榜的字段(玩家名称,关卡号)
LeaderboardModule.addField(FieldType.Name, "玩家名")
LeaderboardModule.addField(FieldType.PointNumber, "关卡号")
LeaderboardModule.showRankField("排名", null, "未上榜")
}
if (SystemUtil.isServer()) {
// 设置存储环境
DataStorage.setTemporaryStorage(SystemUtil.isPIE)
// 数据存储逻辑
Event.addClientListener("SavePoint", (player: Player, pointNumber: number) => {
// 使用数据中心存储数据
// 改变数据
DataCenterS.getData(player, LevelData).pointNumber = pointNumber
// 存储数据
DataCenterS.getData(player, LevelData).save(true)
LeaderboardModule.setPlayerValue(player, FieldType.PointNumber, pointNumber)
LeaderboardModule.setPlayerValue(player, FieldType.Name, player.character.displayName)
})
// 当玩家进入游戏,向排行榜添加一条数据
Player.onPlayerJoin.add((player: Player) => {
LeaderboardModule.addPlayer(player)
})
// 当玩家退出游戏,将数据从排行榜上删除
Player.onPlayerLeave.add((player: Player) => {
LeaderboardModule.removePlayer(player)
})
}
}
}
4.将角色头顶昵称设置为233昵称
当游戏发布到线上之后,角色的头顶昵称一般都会使用233的用户昵称,具体代码如下:
GameStart脚本:
在客户端启动的时候,通过 SystemUtil.isPIE 判断运行环境是编辑器环境还是线上环境。
如果是编辑器环境,就使用玩家名+userID的形式设置头顶昵称;
如果是线上环境,就通过AccountService.getNickName()获取到233昵称并设置。
ts
import { LevelData } from "./LevelData";
import { LevelManager } from "./LevelManager";
import GameUI from "./UI/GameUI";
import { HelperUI } from "./UI/HelperUI";
/**所有的排行榜字段 */
export enum FieldType{
Name,
PointNumber
}
@Component
export default class GameStart extends Script {
/** 当脚本被实例后,会在第一帧更新前调用此函数 */
protected async onStart(): Promise<void> {
if(SystemUtil.isClient()){
LevelManager.instance.init()
UIService.show(HelperUI);
// 将头顶昵称设置为233昵称
const player = Player.localPlayer
// 当游戏运行在编辑器上,是获取不到233昵称的
if(SystemUtil.isPIE){
player.character.displayName = "玩家名"+player.userId
}else{
player.character.displayName = AccountService.getNickName()
}
// 在客户端设置排行榜的样式
LeaderboardModule.setStyle("排行榜",true,10,5)
// 设置排行榜的字段(玩家名称,关卡号)
LeaderboardModule.addField(FieldType.Name,"玩家名")
LeaderboardModule.addField(FieldType.PointNumber,"关卡号")
LeaderboardModule.showRankField("排名",null,"未上榜")
}
if(SystemUtil.isServer()){
// 设置存储环境
DataStorage.setTemporaryStorage(SystemUtil.isPIE)
// 数据存储逻辑
Event.addClientListener("SavePoint",(player:Player,pointNumber:number)=>{
// 使用数据中心存储数据
// 改变数据
DataCenterS.getData(player,LevelData).pointNumber = pointNumber
// 存储数据
DataCenterS.getData(player,LevelData).save(true)
LeaderboardModule.setPlayerValue(player,FieldType.PointNumber,pointNumber)
LeaderboardModule.setPlayerValue(player,FieldType.Name,player.character.displayName)
})
// 当玩家进入游戏,向排行榜添加一条数据
Player.onPlayerJoin.add((player:Player)=>{
LeaderboardModule.addPlayer(player)
})
// 当玩家退出游戏,将数据从排行榜上删除
Player.onPlayerLeave.add((player:Player)=>{
LeaderboardModule.removePlayer(player)
})
}
}
}
import { LevelData } from "./LevelData";
import { LevelManager } from "./LevelManager";
import GameUI from "./UI/GameUI";
import { HelperUI } from "./UI/HelperUI";
/**所有的排行榜字段 */
export enum FieldType{
Name,
PointNumber
}
@Component
export default class GameStart extends Script {
/** 当脚本被实例后,会在第一帧更新前调用此函数 */
protected async onStart(): Promise<void> {
if(SystemUtil.isClient()){
LevelManager.instance.init()
UIService.show(HelperUI);
// 将头顶昵称设置为233昵称
const player = Player.localPlayer
// 当游戏运行在编辑器上,是获取不到233昵称的
if(SystemUtil.isPIE){
player.character.displayName = "玩家名"+player.userId
}else{
player.character.displayName = AccountService.getNickName()
}
// 在客户端设置排行榜的样式
LeaderboardModule.setStyle("排行榜",true,10,5)
// 设置排行榜的字段(玩家名称,关卡号)
LeaderboardModule.addField(FieldType.Name,"玩家名")
LeaderboardModule.addField(FieldType.PointNumber,"关卡号")
LeaderboardModule.showRankField("排名",null,"未上榜")
}
if(SystemUtil.isServer()){
// 设置存储环境
DataStorage.setTemporaryStorage(SystemUtil.isPIE)
// 数据存储逻辑
Event.addClientListener("SavePoint",(player:Player,pointNumber:number)=>{
// 使用数据中心存储数据
// 改变数据
DataCenterS.getData(player,LevelData).pointNumber = pointNumber
// 存储数据
DataCenterS.getData(player,LevelData).save(true)
LeaderboardModule.setPlayerValue(player,FieldType.PointNumber,pointNumber)
LeaderboardModule.setPlayerValue(player,FieldType.Name,player.character.displayName)
})
// 当玩家进入游戏,向排行榜添加一条数据
Player.onPlayerJoin.add((player:Player)=>{
LeaderboardModule.addPlayer(player)
})
// 当玩家退出游戏,将数据从排行榜上删除
Player.onPlayerLeave.add((player:Player)=>{
LeaderboardModule.removePlayer(player)
})
}
}
}
5.在HelperUI中,添加排行榜按钮
打开HelperUI,拖动一个文本按钮到图中位置,并将按钮名字修改为mLeaderBoard_btn,最后点击“导出所有脚本”
在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.onPressed.add(()=>{
LevelManager.instance.jumpToPoint()
})
// 跳关功能
this.mJump_btn.onPressed.add(()=>{
LevelManager.instance.jumpToPoint( Number(this.mJump_input.text))
})
this.mLeaderBoard_btn.onPressed.add(()=>{
LeaderboardModule.showPanel()
})
}
}
import { LevelManager } from "../LevelManager";
import HelperUI_Generate from "../ui-generate/HelperUI_generate";
export class HelperUI extends HelperUI_Generate{
protected onAwake(): void {
// 复位功能
this.mRest_btn.onPressed.add(()=>{
LevelManager.instance.jumpToPoint()
})
// 跳关功能
this.mJump_btn.onPressed.add(()=>{
LevelManager.instance.jumpToPoint( Number(this.mJump_input.text))
})
this.mLeaderBoard_btn.onPressed.add(()=>{
LeaderboardModule.showPanel()
})
}
}