Search Unity

(Solved) UWP (Xbox Live) Creators Cloud Save (Connected Storage) Issue

Discussion in 'Windows' started by John-Lisenby, Apr 3, 2019.

  1. John-Lisenby

    John-Lisenby

    Joined:
    Nov 8, 2013
    Posts:
    110
    Hello,

    I found a bug in ILC2PP bug report https://issuetracker.unity3d.com/issues/il2cpp-uwp-xbox-live-il2cpp-builds-sometimes-return-null-string-values-on-uwp-with-xbox-live-connected-storage , and yesterday I got feedback saying Unity will not fix the issue because small customer base is reporting the issue. However when I checked today, the Issue Tracker it now shows active.

    Can I get a real update? I would like to republish my game once I get this issue resolved. Microsoft pulled my game in January when they / I first discovered the bug.

    In the resolution, they suggested a try catch and retry, and I'm still unable to get it working. Any help would be great.

    If anyone else has any advice or wants to look into this issue, this is dealing with the Unity Xbox Live Plugin using IL2CPP with Connected Storage.

    Thanks,

    John
     
  2. PJayB

    PJayB

    Unity Technologies

    Joined:
    Apr 24, 2017
    Posts:
    105
    Hi John,

    Thank you for raising this with us. I'm the engineer that investigated this issue and made the decision to resolve this as Won't Fix. Right off the bat, I'd like to apologize for not following up with more information via email when I closed the bug.

    I'll break down my reasoning to give you an opportunity to correct any assumptions I got wrong, and then we can work on solutions that will help unblock you.

    Here are some factors I was considering:
    • When looking at your bug as well as discussing with the QA engineer who forwarded it to us, it appeared that this issue had a very low reproducible rate. (If this is not true for you, let me know.)
    • It involves a 3rd party plugin (Xbox Live) that is open source. While no callstack was provided with the bug, your videos contained partial stacks that indicated that the exception is thrown from inside this plugin (Microsoft.Xbox.Services.ConnectedStorage.GameSaveHelper.Initialize).
    • The API calls used by Xbox Live are merely wrappers around Windows' C++ APIs. However, as you point out, this only reproduces when using IL2CPP so I acknowledge that there is an internal behavioral difference somewhere between the IL2CPP and .NET backends.
    While there is an inconsistency between .NET and IL2CPP in this case, I decided to close your bug specifically for two reasons:
    1. Any inconsistency between .NET and IL2CPP here would be covered by another, more reliably reproducible bug,
    2. The calling code can be potentially debugged and modified to work around this issue.
    For example of #1, I found this, which seems related because `XboxLiveUser.WindowsSystemUser` returns null and I'm willing to bet this is true in your case.

    As for #2, I think it would be easier and faster for you to work around this issue by debugging and/or modifying the Xbox Live plugin source, rather than have you wait any longer for us to reliably reproduce, fix, test and release a patch update. The fact that we cannot consistently reproduce this issue either would add more time.

    I suggest starting by verifying the inputs to GameSaveProvider.GetForUserAsync on line 41 of GameSaveHelper.cs in the Xbox Live plugin. If they look good, try putting a try/catch around that call and retrying if it fails. If they look bad, please use a managed debugger to trace back to the point of failure. Either way, please post your findings with the appropriate stacks and other relevant info and we can investigate.
     
  3. John-Lisenby

    John-Lisenby

    Joined:
    Nov 8, 2013
    Posts:
    110
    Hi @PJayB

    Thanks for the rely. This error happens all the time in my game ever since I upgrade to IL2CPP. When working to reproduce the bug with the Unity bug reporting bug team, he only seen it happen a few times. However in my case, it happens all the time after the game is launched and closed the first time. (On a clean project with just the plug in.) If you reboot, the issue sometimes doesn't happen.

    I have tried the try catch retry, and it seems not to work correctly. Then again I could be doing it incorrectly. I have a small testing project just with the plugin. I can send it to you again.

    I'll do stack trace and upload it here. I'm just happy to have someone help me with this issue. I have spent months reaching out to someone at Microsoft that's working with the plug-in, and I cannot get anyone to help address this issue. Like it said earlier, Microsoft removed my game because of this function not working. I haven't republished it because if this issue.

    Thanks again,

    John
     
  4. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    6,420
    Thanks for that information. We definitely misread the bug report - sorry about that. I'll try looking at it next week.
     
  5. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    6,420
    Hi,

    I looked at it today and I do not think this is a bug in Unity. In fact, it's a race condition in this C# code:

    https://github.com/Microsoft/xbox-live-unity-plugin/blob/master/Assets/Xbox Live/Scripts/SignInManager.cs#L126

    You can't just start an async operation and instantly query for its completion. It might be ready immediately, it might not be. That code is full of patterns like this... bugs lurking to be triggered.

    Anyway, I replaced this block:

    Code (csharp):
    1. var usersTask = Windows.System.User.FindAllAsync().AsTask();
    2. if (usersTask.Status == TaskStatus.RanToCompletion && usersTask.Result != null && usersTask.Result.Count > 0)
    3. {
    4.    var windowsUser = usersTask.Result[0];
    5.    this.CurrentPlayers[playerNumber].WindowsUser = windowsUser;
    6.    this.CurrentPlayers[playerNumber].XboxLiveUser = new XboxLiveUser(windowsUser);
    7.    this.StartCoroutine(this.SignInAsync(playerNumber, this.CurrentPlayers[playerNumber]));
    8. }
    9. else
    10. {
    11.    this.CurrentPlayers[playerNumber].XboxLiveUser = new XboxLiveUser();
    12.    XboxLiveUser.SignOutCompleted += XboxLiveUserSignOutCompleted;
    13.    this.StartCoroutine(this.SignInAsync(playerNumber, this.CurrentPlayers[playerNumber]));
    14. }
    With this code:

    Code (csharp):
    1. var usersTask = Windows.System.User.FindAllAsync().AsTask();
    2. CompleteSignIn(playerNumber, usersTask);
    3.  
    4. ...
    5.  
    6. #if ENABLE_WINMD_SUPPORT
    7. private async void CompleteSignIn(int playerNumber, Task<IReadOnlyList<User>> usersTask)
    8. {
    9.    var result = await usersTask;
    10.    if (result != null && result.Count > 0)
    11.    {
    12.        var windowsUser = result[0];
    13.        this.CurrentPlayers[playerNumber].WindowsUser = windowsUser;
    14.        this.CurrentPlayers[playerNumber].XboxLiveUser = new XboxLiveUser(windowsUser);
    15.        this.StartCoroutine(this.SignInAsync(playerNumber, this.CurrentPlayers[playerNumber]));
    16.    }
    17.    else
    18.    {
    19.        throw new Exception("Something failed");
    20.    }
    21. }
    22. #endif
    And the problem went away.
     
  6. John-Lisenby

    John-Lisenby

    Joined:
    Nov 8, 2013
    Posts:
    110
    Hi @Tautvydas-Zilys

    Thank you for looking into this issue and taking the time to fix it! I'll pass along this fix to others on the Xbox plug-in forms.

    Thanks again,

    John