Unity接入GooglePlayGames登陆与OpenSaveGame踩坑

接入API网上很多,这里放几个链接,大家参考,本文只讲我遇到的坑点

GitHub官方文档,讲的比较全面

视频讲解登陆接入(里面有登入Unity账号的部分,没有需要的可以略着看)

GooglePlayGame玩家数据存储

一、GooglePlayGames插件导入

正常来说,导入GooglePlayGames插件后,不需要额外操作,但可能还是会打包失败,报错:找不到GooglePlayGames库

可以尝试以下操作 

1.找到文件Assets/GooglePlayGames/com.google.play.games/GooglePlayGamesPluginDependencies.xml

把文件中

<repository>Packages/com.google.play.games/Editor/m2repository</repository>

修改为

<repository>Assets/GooglePlayGames/com.google.play.games/Editor/m2repository</repository>

2.执行:Assets->External Dependency Manager->Android Resolver->Force Resolve

查看GeneratedLocalRepo目录中是否有GooglePlayGames目录

如果以上两步操作都没有问题,打包时还是提示找不到GooglePlayGames库,可以尝试把GooglePlayGames库全部删掉,重新导入,重新执行上述两步。

二、登录失败

如果我们调用登录是这样写的:

PlayGamesPlatform.Instance.Authenticate();
在某些情况,可能会返回失败,这时我们在失败中,再加入下面这句,是可以成功。
PlayGamesPlatform.Instance.ManuallyAuthenticate();

四、签名问题

我们可能会遇到打的APK可以登陆,但打的aab包,或从商店下载的包无法登陆;我们把证书指纹修改为发布证书,导致APK又无法登陆,都是因为证书问题

正确配置需要有两个凭据

一个对应调试证书

一个对应发布证书

有两个凭据,需要有一个勾选:“新安装的应用将使用此凭据”

按照谷歌的说法,应该是发布证书勾选才对,但实际,从商店下载的包会登陆失败,最后我尝试将调试证书勾选,莫名其秒的成功了,无论是APK,还是从商店下载的,都没有问题。具体什么原因,我没有搞明白,如果哪位知道原因,请在评论区留言,感谢!

四、手机中必须安装Google Play 游戏APP

刚开始我手机中没有安装GooglePlay游戏APP,一直登入失败,导致我浪费了半天时间。

我们开发中也要考虑这个问题,如果玩家的手机没有安装,导致登陆失败,开发者应该处理这种情况。

这是我的登陆代码,供大家参教

private bool manuallyAuthenticate = false;

void Awake()
{
    PlayGamesPlatform.Activate();
}

public override void Login() {
	SDKChannel.SDKLog($"点击登陆");

	manuallyAuthenticate = false;
	PlayGamesPlatform.Instance.Authenticate(OnAuthenticationFinished);
}

private void OnAuthenticationFinished(SignInStatus status)
{
	SDKChannel.SDKLog($"登陆回调 status:{status}");
	if (status == SignInStatus.Success)
	{
		JObject callObj = new JObject();
		callObj["UserId"] = PlayGamesPlatform.Instance.GetUserId();	//用户ID
		callObj["UserName"] = PlayGamesPlatform.Instance.GetUserDisplayName();	//用户名字
		SDKChannel.OnSDKCallback((int)ESDKCallType.LoginSuccess, callObj);
	}
	else
	{
		if (manuallyAuthenticate == false)
		{
			PlayGamesPlatform.Instance.ManuallyAuthenticate(OnAuthenticationFinished);
			manuallyAuthenticate = true;
		}
		else
		{
			JObject callObj = new JObject();
			callObj["Status"] = status.ToString();	//状态
			SDKChannel.OnSDKCallback((int)ESDKCallType.LoginFailure, callObj);
		}
	}
}

五、云存储

刚开始我的写法是,在游戏启动时,打开游戏存储(OpenSaveGame),把获得到的game(ISavedGameMetadata game)对象存起来,在游戏中每1分钟调用一次保存游戏(SaveGame)

听上去没有问题,平时的编程思路都是这样

但实际测试,每打开一次游戏存储(OpenSaveGame)时获得的game对象,在保存时,只能使用一次

即:每次保存,必须先去打开游戏对象

这让我有点难以理解,但实际测试是这个样子,如果我的理解有错,欢迎评论留言。

云存储完整代码

/// <summary>
/// 保存玩家游戏数据
/// </summary>
public class SDKGameDataGoogle
{
    private static SDKGameDataGoogle _instance;

    public static SDKGameDataGoogle Instance
    {
        get
        {
            if (_instance == null)
            {
                _instance = new SDKGameDataGoogle();
            }

            return _instance;
        }
    }

    private bool _isSaveing;
    private Action _action;

    private JObject _saveJObject;

    private string filename = "data1";

    //打开游戏存档
    public void OpenGame(Action action)
    {
        _isSaveing = false;
        _action = action;

        Debug.Log($"11 打开游戏存档");

        if (!this.OpenSavedGame())
        {
            _action?.Invoke();
        }
    }

    public void SaveGame(JObject jObject)
    {
        _isSaveing = true;
        _saveJObject = jObject;

        Debug.Log($"11 保存游戏存档");
        this.OpenSavedGame();
    }

    private bool OpenSavedGame()
    {
        if (PlayGamesPlatform.Instance == null || PlayGamesPlatform.Instance.SavedGame == null)
        {
            return false;
        }
        ISavedGameClient savedGameClient = PlayGamesPlatform.Instance.SavedGame;
        savedGameClient.OpenWithAutomaticConflictResolution(filename, DataSource.ReadCacheOrNetwork,
            ConflictResolutionStrategy.UseOriginal, OnSavedGameOpened);
        return true;
    }

    //打开完成
    private void OnSavedGameOpened(SavedGameRequestStatus status, ISavedGameMetadata game) {

        Debug.Log($"打开保存的游戏--回调{status}");

        if (_isSaveing)
        {
            if (status == SavedGameRequestStatus.Success)
            {
                byte[] savedData = System.Text.Encoding.UTF8.GetBytes(this._saveJObject.ToJson(Formatting.None));
                this.SaveGame(game, savedData);
            }
        }
        else
        {
            if (status == SavedGameRequestStatus.Success)
            {
                ISavedGameClient savedGameClient = PlayGamesPlatform.Instance.SavedGame;
                savedGameClient.ReadBinaryData(game, OnSavedGameDataRead);
            }
            else
            {
                _action?.Invoke();
            }
        }
    }

    //拿到元数据
    private void OnSavedGameDataRead (SavedGameRequestStatus status, byte[] data) {
        Logger.LogError($"拿到玩家数据, status:{status}, data.length:{data.Length}");
        if (status == SavedGameRequestStatus.Success)
        {
            JObject jObject = null;
            try
            {
                string json = System.Text.Encoding.UTF8.GetString(data);
                jObject = JObject.Parse(json);
            }
            catch (Exception e)
            {
                jObject = new JObject();
            }

            CSPlayerSettings.InitializedPlayerData(jObject, "googleplaygames", PlayGamesPlatform.Instance.GetUserId());
        }
        _action?.Invoke();
    }

    private void SaveGame(ISavedGameMetadata game, byte[] savedData) {
        Debug.Log($"22 保存游戏存档");
        ISavedGameClient savedGameClient = PlayGamesPlatform.Instance.SavedGame;

        SavedGameMetadataUpdate.Builder builder = new SavedGameMetadataUpdate.Builder();
        builder = builder.WithUpdatedDescription("Saved game at " + DateTime.Now);

        SavedGameMetadataUpdate updatedMetadata = builder.Build();
        savedGameClient.CommitUpdate(game, updatedMetadata, savedData, OnSavedGameWritten);
    }

    private void OnSavedGameWritten (SavedGameRequestStatus status, ISavedGameMetadata game) {
        Debug.Log($"33 保存游戏存档结果:{status}");
    }
}

文章最后,吐槽一下Unity提供的CloudData

最初我的想法是,接入GoogleSign与Unity的CloudData实现登陆与存储玩家数据,GoogleSign以前已经接过,不用再踩坑,另外发布苹果时,就不用再写一遍苹果存储问题。

一切进行的都很顺利,测试也都通过了,但在两天后,请求加载CloudData时,Unity返回错误:There was a validation error. Check 'Details' for more information

我拿着这个错误去Google搜索,一点资料也没有,尝试清理缓存,还是返回一样的错误。

在我测试的前两天都很正常,突然返回这个错误,且,一旦发生,就是不可逆的,玩家数据彻底丢失!

想不出原因后,无奈只得放弃,重新接入GooglePlayGames​​​​...(。•ˇ‸ˇ•。) ...

当然,如果有哪位大佬知道原因,请在评论区留言,感谢!

  • 24
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值