Unity iOS 无服务器做一个排行榜 GameCenter

Posted 时光不染

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unity iOS 无服务器做一个排行榜 GameCenter相关的知识,希望对你有一定的参考价值。

排行榜

需求

需求:接入排行榜,每关都有单独的分数排行,在关卡结束后可点击弹出或主动弹出。
ps:没有做自己的服务器统计数据及好友关系等

解决方案一(嗯目前只有一)

UnityEngine.SocialPlatforms

UnityEngine.SocialPlatforms API点这里

Unity社交模型,集成了一些诸如好友,排行,成就等功能。

我这里只接入了iOS,所以以下只做iOS的分析

优点 使用方便,使用方便,使用方便,不用导入sdk什么的,Unity做了封装
缺点 Unity做了封装,但有些api并不好用。另外,玩家只有开启GameCenter才能使用本功能。再另外,面板并不是很好看

o(╥﹏╥)o

 
默认情况下,在 iOS 上使用 GameCenter。其他所有 平台均默认为可用于测试的本地实现,android 一般用Google Play Games
 

iOS GameCenter

iOS GameCenter 能设置500个排行榜(并没有看到官方文档,据说有那么多),足够用了。
 

AppStoreConnect配置

重复以上步骤,需要几个排行榜加几个,暂时没找到批量的方法

Unity 调用(如果使用GameCenter系统的面板,看到这里就可以了)
using UnityEngine;
using UnityEngine.SocialPlatforms;

namespace HZH

    public class RankingList
    
        private static RankingList _instance;

        public RankingList Instance => _instance??new RankingList();

        public void Init ()
        
            if (Application.platform == RuntimePlatform.IPhonePlayer) 
                Social.localUser.Authenticate (success =>
                
                    Debug.Log(success ? "GameCenter初始化成功" : "GameCenter初始化失败");
                );
            
        
        /// <summary>
        /// 上传数据
        /// </summary>
        /// <param name="score">分数</param>
        /// <param name="leaderboardID">指定的排行榜id</param>
        public void ReportScore (long score, string leaderboardID)
        
            if (Application.platform != RuntimePlatform.IPhonePlayer) return;
            if (Social.localUser.authenticated) 
                Social.ReportScore (score, leaderboardID, success =>
                
                    Debug.Log(success
                        ? $"GameCenter:leaderboardID分数score上报成功"
                        : $"GameCenter:leaderboardID分数score上报失败");
                );
            
        
        /// <summary>
        /// 拉起排行榜数据
        /// </summary>
        public void ShowLeaderboard ()
        
            if (Application.platform != RuntimePlatform.IPhonePlayer) return;
            if (!Social.localUser.authenticated) return;

            Social.ShowLeaderboardUI ();
        

        /// <summary>
        /// 获取指定排行榜数据
        /// </summary>
        /// <param name="boardId"></param>
        public void GetBoardData(string boardId)
        
            if (Application.platform != RuntimePlatform.IPhonePlayer) return;
            ILeaderboard leaderboard = Social.CreateLeaderboard();
            leaderboard.id = boardId;
            leaderboard.LoadScores(result =>
            
                Debug.Log("Received " + leaderboard.scores.Length + " scores");
                foreach (IScore score in leaderboard.scores)
                    Debug.Log(score);
            );
        

    


如果团队愿意用Native的GameCenter排行榜界面,这里ShowLeaderboard已经能完成了。初始化,数据上报,拉取排行榜面板。

面板在不同机型上显示也不一样,以下是一种机型作参考

 

(需要获取数据做自定义面板的看这里)

如果native面板不满足需求,就需要拿到排行榜数据,自己做实现。
上面的代码GetBoardData方法并不能正确获取到玩家昵称数据。测试2个账号,一个昵称显示未知,一个获取数据失败。账号所限,没办法测试更多了。

这里我找到的解决方案是在iOS直接调用Native的api获取数据

iOS代码

GameCenterCtrl.h

@interface GameCenterCtrl : NSObject  // 声明需要的字段


-(void)GetRankingListData:(const char*)boardId;
@end

GameCenterCtrl.m

#import <Foundation/Foundation.h>
#import <GameKit/GameKit.h>
#import "GameCenterCtrl.h"

@implementation GameCenterCtrl
-(id)init 

    return self;

-(void) GetRankingListData:(const char*)boardId
    GKLeaderboard *leaderboardRequest = [[GKLeaderboard alloc] init];
   if (leaderboardRequest != nil)
    
        NSString* board = [[NSString alloc] initWithUTF8String:boardId];
        leaderboardRequest.playerScope = GKLeaderboardPlayerScopeGlobal;
        leaderboardRequest.timeScope = GKLeaderboardTimeScopeAllTime;
        leaderboardRequest.range = NSMakeRange(1,10);
        leaderboardRequest.identifier = board;
        [leaderboardRequest loadScoresWithCompletionHandler: ^(NSArray *scores, NSError *error) 
            if (error != nil)
                // handle the error.
                NSLog(@"下载失败@");
                NSLog(@"%@", error);
            
           if (scores != nil)
               // process the score information.
               NSLog(@"下载成功....");
               NSArray *tempScore = [NSArray arrayWithArray:leaderboardRequest.scores];
               NSMutableArray* array = [NSMutableArray arrayWithCapacity:tempScore.count];
               for (GKScore *obj in tempScore) 
                    GKPlayer *player = obj.player;
                    NSString *point = [NSString stringWithFormat:@"%lld", obj.value];
                    NSString *rank = [NSString stringWithFormat:@"%ld", obj.rank];
                    NSDictionary *dict = @
                                         @"name":player.alias,
                                         @"point":point,
                                         @"rank":rank,
                                         ;
                    [array addObject:dict];
                
               
               NSData *data = [NSJSONSerialization dataWithJSONObject:array options:kNilOptions error:nil];
               NSLog(@"u3d_packageJosn data: %@", data);

               // nsdata -> nsstring
               NSString *jsonString = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
               NSLog(@"u3d_packageJosn jsonString: %@", jsonString);

               // nsstring -> const char*
               const char* constStr = [jsonString UTF8String];
        		
               UnitySendMessage(你的GameObject名字, 接收数据的方法名, constStr);
            
       ];
   
   

@end

PortFile.h

#import <Foundation/Foundation.h>

@interface PortFile : NSObject
void GetRankingListData(const char* boardId);
@end

PortFile.m

#import "PortFile.h"
#import "GameCenterCtrl.h"
// 这个对象用来接收Unity信息,处理OC代码
void showAppStoreScoreView()
    [[GameCenterCtrl alloc]GetRankingListData:boardId];


以上4个文件放到Assets/Plugins/ios 文件夹下,GameCenterCtrl也可以直接按PortFile的写法,省了portFile俩文件。 或者用自己的unity2iOS通信方案,核心就GameCenterCtrl.mGetRankingListData方法。

Unity 代码

获取数据

	[DllImport("__Internal")]
    private static extern void GetRankingListData(string boardId);
	
	public void GetRankingData(string boardId)
		GetRankingListData(boardId)
	

接收数据(数据获取是异步进行的,所以用的UnitySendMessage),这个Unity接收数据想来都懂,就不一步步写了。拿到数据json解一下就可以为所欲为了

吐槽

搜索Unity排行榜,帖子茫茫多,全是教怎么写界面的,写界面用你教呀 -_-||

以上是关于Unity iOS 无服务器做一个排行榜 GameCenter的主要内容,如果未能解决你的问题,请参考以下文章

Google Play Game Services Unity:更新排行榜或解锁成就时手机重启

如何更改 Game Center (iOS) 中的排行榜图标?

iOS Game Center 将排行榜和成就移动到 2 个游戏的组中

基于cocos2dx,在android的游戏中加入google play game排行榜。

“没有挑战”消息 Game Center iOS 8

Google Play 服务 Unity 插件显示排行榜