为什么在Unity应用程序中没有互联网连接时,Social.localUser.Authenticate会导致崩溃?

时间:2016-02-27 20:18:00

标签: ios unity3d game-center unity5 unity3d-2dtools

通过互联网连接

一切都完美无瑕。没有导致崩溃的内存问题。

没有互联网连接

应用程序进入菜单屏幕,最终崩溃,因为内存不足。

我的结论是问题在于以下代码行

Social.localUser.Authenticate

当我注释掉上述行时,如果没有互联网连接,内存问题就会消失。

这是我的相关代码

void Start () 
{
    Social.localUser.Authenticate(ProcessAuthentication);
}

public void ProcessAuthentication(bool success) 
{
    if(success)
        Debug.Log ("Authenticated");
    else
        Debug.Log ("Failed to authenticate");
}

导致崩溃

2016-02-27 15:46:37.131 BrickBall[449:60670] Received memory warning.
WARNING -> applicationDidReceiveMemoryWarning()
2016-02-27 15:46:37.302 BrickBall[449:60670] Received memory warning.
WARNING -> applicationDidReceiveMemoryWarning()
2016-02-27 15:46:37.349 BrickBall[449:60670] Received memory warning.
WARNING -> applicationDidReceiveMemoryWarning()
2016-02-27 15:46:37.437 BrickBall[449:60670] Received memory warning.
WARNING -> applicationDidReceiveMemoryWarning()
Message from debugger: Terminated due to memory issue

为什么在没有互联网连接的情况下,这行代码会导致内存不足崩溃?

1 个答案:

答案 0 :(得分:1)

我的猜测是你最终需要和Unity交谈。当没有网络连接时,游戏中心将使用缓存凭据来报告它已成功连接到服务器并进行身份验证,即使它没有。我在这方面打开了一个错误 - 并且正在与苹果进行讨论。此行为允许某些游戏类型即使在没有网络时也能继续,然后在连接恢复后再进行同步。但是,我遇到了问题,我认为我可以做的事情,因为GC说它已经过验证,但我真的不能,因为它确实没有。 :/

这意味着应用程序必须处理三种情况:

  • 使用GC成功验证
  • 使用GC验证失败
  • 身份验证失败,但根据缓存数据报告为成功

Unity可能无法处理第三种情况。要确认或反驳此信息,请尝试以下操作:

确认Unity确实干净地处理了身份验证失败

  1. 建立连接

  2. 退出游戏中心

  3. 中断连接(飞行模式等)

  4. 重试您的应用

  5. 我希望success在这一点上是假的,并且干净利落地运行。

    如果按预期工作,我会与Unity讨论他们如何在断开连接的情况下处理Game Center报告(缓存)成功。

    <强> EDIT2:

    我不得不回去查看我的代码,看看我是如何对抗它的。场景是:完全断开连接和/或在飞机模式下,Game Center正在显示“欢迎回来”消息,localPlayer.authenticated设置为YES ...但是,错误代码已设置并正在抱怨它无法连接。

    我打开了错误22232706,“[GKLocalPlayer localPlayer] .authenticated在设置任何身份验证处理程序后始终返回true”,并且仍在进行讨论。 Apple证实了这一行为,但表示其意图。

    以下是我如何强化我的身份验证处理程序来处理这种情况。它不会帮助你,因为Unity正在为你处理这个问题,但我认为其他读者可能会觉得这很有帮助。 (TL; DR版本:始终始终 始终首先检查错误代码,然后再检查.authenticated或检查viewController是否为[localPlayer setAuthenticateHandler:^(UIViewController *loginViewController, NSError *error) { //Note: this handler fires once when you call setAuthenticated, and again when the user completes the login screen (if necessary) //did we get an error? Could be the result of either the initial call, or the result of the login attempt //Very important: ALWAYS check `error` before checking for a viewController or .authenticated. if (error) { //Here's a fun fact... even if you're in airplane mode and can't communicate to the server, //when this call back fires with an error code, localPlayer.authenticated is sometimes set to YES despite the total failure. >< //combos seen so far: //error.code == -1009 -> authenticated = YES //error.code == 2 -> authenticated = NO //error.code ==3 -> authenticated = YES if ([GKLocalPlayer localPlayer].authenticated == YES) { NSLog(@"error.code = %ld but localPlayer.authenticated = %d", (long)error.code, [GKLocalPlayer localPlayer].authenticated); } //Do stuff here to disable network play, disable buttons, warn users, etc. return; } //if we received a loginViewContoller, then the user needs to log in. if (loginViewController) { //the user isn't logged in, so show the login screen. [rootVC2 presentViewController:loginViewController animated:NO completion:^ { //was the login successful? if ([GKLocalPlayer localPlayer].authenticated) { //enable network play, or refresh matches or whatever you need to do... } }]; } //if there was not loginViewController and no error, then the user is alreay logged in else { //the user is already logged in //refresh matches, leaderboards, whatever you need to do... } }]; 设置)

    {{yield this}}