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排行榜,帖子茫茫多,全是教怎么写界面的,写界面用你教呀 -_-||

猜你喜欢

转载自blog.csdn.net/hzhnzmyz/article/details/129045819