接入API网上很多,这里放几个链接,大家参考,本文只讲我遇到的坑点
视频讲解登陆接入(里面有登入Unity账号的部分,没有需要的可以略着看)
一、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...(。•ˇ‸ˇ•。) ...
当然,如果有哪位大佬知道原因,请在评论区留言,感谢!