Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Feedback UGS offline behaviour is awful

Discussion in 'Unity Gaming Services General Discussion' started by VoxelMatt, Aug 15, 2022.

  1. VoxelMatt

    VoxelMatt

    Joined:
    Apr 22, 2015
    Posts:
    42
    Can someone explain to me why Unity Gaming Services uses exceptions to manage basic error codes like "The internet is unreachable"?

    This is awful to deal with as a programmer. The functionality is not at all obvious from the API and requires reading documentation or just waiting until you catch an exception and realise that you need to wrap _every_ call in a try/catch.

    Furthermore NONE of the sample projects wrap initialisation in TRY/CATCH. WHY? Has no-one at unity ever tested this functionality offline? Is there some basic programming knowledge that's changed in the last few years that I'm missing?

    Please help me understand so I'm not overwhelmed with frustration.
     
    PeachyPixels and danielalindan like this.
  2. PeachyPixels

    PeachyPixels

    Joined:
    Feb 17, 2018
    Posts:
    704
    I share your frustration, offline support with the UGS services is really lacking.

    What frustrates me is that each UGS service handles things differently. Some use Tasks, others don't. Some raise exceptions, others don't. Some use callbacks, others don't. Some handle retries, others don't.

    I feel if Unity could focus on the following, the usability of their API's would increase dramatically...

    1. Consistency across all UGS services
    2. Unity handling exceptions (for init\connectivity functionality)
    3. Unity handling retry scenarios (for init\connectivity functionality)
    4. Raising all retry\success\fail scenarios via callbacks or events

    I've raised these issues with Unity before and they have responded positively so far thankfully. Let's hope they're seriously looking into improvements like these as a priority.
     
    danielalindan and VoxelMatt like this.
  3. tony_c-unity3d

    tony_c-unity3d

    Unity Technologies

    Joined:
    Jul 18, 2019
    Posts:
    35
    @VoxelMatt,

    Thanks for the feedback. I can't speak for all UGS Services as I work primarily on the Samples team, but wanted to follow up on that part of your post. I just double-checked all our samples (as are referenced at https://docs.unity.com/ugs-use-cases/Welcome.html ) and it does appear that all wrap calls to initialization with try/catch. As an example, Daily Rewards Use Case initializes in DailyRewardsSceneManager.cs Start() method, which begins:

    Code (CSharp):
    1.             async void Start()
    2.             {
    3.                 try
    4.                 {
    5.                     await UnityServices.InitializeAsync();
    I double-checked all our UGS Use Case samples and they all initialize within a try/catch block so I'm probably just misunderstanding your comment. If so, I apologize; if you can clarify a bit, I'll try to get you more information and/or pass your suggestion to our lead.

    Thanks again for your feedback and have a great day!
     
  4. VoxelMatt

    VoxelMatt

    Joined:
    Apr 22, 2015
    Posts:
    42
    Samples missing try/catch:

    Remote Config:

    Analytics:


    Authentication:
     
  5. VoxelMatt

    VoxelMatt

    Joined:
    Apr 22, 2015
    Posts:
    42
    Furthermore... did the UGS team chat to the Unity Crash Reporting team when deciding to use Exceptions to manage basic application flow? My crash reports are full of exceptions now that aren't actually useful to me in the slightest.

    So I guess now I should wrap my calls to `Debug.LogException(...)` with `Debug.isDevelopmentBuild`
     
    danielalindan likes this.
  6. tony_c-unity3d

    tony_c-unity3d

    Unity Technologies

    Joined:
    Jul 18, 2019
    Posts:
    35
    @VoxelMatt ,
    Apologies for the confusion and thank you so much for clarifying. I was definitely looking at other samples when I suggested that they were all wrapped in try/catch.

    I'll pass along your comments to a wider audience to try to get you answers.
     
  7. erika_d

    erika_d

    Joined:
    Jan 20, 2016
    Posts:
    413
    Hi @VoxelMatt and @PeachyPixels,

    Thanks for your feedback about UGS' offline support, use of exceptions, sample code quality, and consistency across services. We really appreciate your using UGS and giving us feedback on your experiences, and rest assured that discussions around these topics are being had, and that getting this kind of feedback from developers using the services is a great addition to these conversations.

    I, like Tony, am on the UGS Samples team, where we're trying to create samples that use multiple Unity Gaming Services integrated together to fulfill common game use cases. Part of the reason for our team's existence is to provide developers like yourselves with best practices for working with the services (like surrounding calls to services with try-catches), but another reason for our team is to provide feedback around consistency of the services and what using the services are like in real game development scenarios. I hope that this helps reassure you that consistency across services is something we're striving and working towards in UGS.

    I'll also try to give some additional context on some of the conversations that have been had about the use of exceptions. It's definitely something that has been looked at from many different angles, and there are pluses and minuses in any direction. Some of the reasons we've been moving in the exceptions direction, is that looking at the C# ecosystem and openAPI generators, etc., use of exceptions is a common and recommended way of handling errors, so there are consistency and other benefits to following the practices and recommendations of the wider C# ecosystem. Further, looking inside Unity's ecosystem, we've got the UnityWebRequest, which is typically considered pretty cumbersome and error prone to work with. That being said, we really want to find a solution that has these benefits, while also being a good experience to work with from the developer side. Though we may not be there yet, our hope is that we can get to a place (with robust documentation, consistent behavior and patterns across services and supporting examples) where handling exceptions is straightforward. (And as a side note, the callout about how exceptions effect crash reporting is a good note that's worth further consideration I think.)

    Finally, regarding offline support, this is a more nascent conversation, and more feedback from you all about what you'd like to see from this respect would be helpful. Which services are most important for you to have offline support? The whole UGS ecosystem, or just certain services? What kind of offline support are you interested in? The kind that tolerates brief internet connection loss like when a player goes through a tunnel? Or a more robust kind where the game can be entirely played without a connection and maybe just certain parts of the game are blocked when offline (like purchasing IAPs, etc)?
     
  8. erickb_unity

    erickb_unity

    Unity Technologies

    Joined:
    Sep 1, 2021
    Posts:
    91
    @VoxelMatt
    Thanks for pointing out the issues with exception handling and crash diagnostics.
    We will look at how we can improve our usage of exceptions and also improve documentation for developers.

    It's important to understand that logging exceptions is an expensive process that needs to be carefully considered.

    Considering crash diagnostics will report all exceptions that are logged/unhandled, here are a few suggestions to improve the experience:

    Option #1:
    Log errors (or warnings) instead from caught exceptions when they are handled gracefully by your game

    Code (CSharp):
    1. try
    2. {
    3.     await UnityServices.InitializeAsync();
    4. }
    5. catch (Exception e)
    6. {
    7.     Debug.LogError(e.Message); // Or e.ToString() which will also provide the exception type
    8.  
    9. }
    Option #2: Create your own logger class
    - If you want to disable certain types of logs in release builds, use [Conditional("DEBUG")] (or any other custom define you may want), this has the added benefit of removing the performance and memory impact of logs in release builds.
    - If you want to convert LogException to LogError in ther internal logic

    Code (CSharp):
    1. using System.Diagnostics;
    2. using Debug = UnityEngine.Debug;
    3.  
    4. public static class GameLogger
    5. {
    6.     [Conditional("DEBUG")]
    7.     public static void Log(string msg)
    8.     {
    9.         Debug.Log(msg);
    10.     }
    11.  
    12.     [Conditional("DEBUG")]
    13.     public static void LogWarning(string msg)
    14.     {
    15.         Debug.LogWarning(msg);
    16.     }
    17.  
    18.     [Conditional("DEBUG")]
    19.     public static void LogError(string msg)
    20.     {
    21.         Debug.LogError(msg);
    22.     }
    23.  
    24.     [Conditional("DEBUG")]
    25.     public static void LogException(System.Exception e)
    26.     {
    27.         Debug.LogException(e);  
    28.         // Optionally replace with Debug.LogError(e.Message);
    29.  
    30.     }
    31. }
    Thanks for the feedback!
     
    Last edited: Aug 24, 2022
    erika_d likes this.
  9. Rabadash8820

    Rabadash8820

    Joined:
    Aug 20, 2015
    Posts:
    94
    @erickb_unity

    Not to derail the conversation, but I'm a little confused why removing logs from release builds is desirable. I've seen this recommendation elsewhere (including the docs on Unity's Assertion system) and its never seems reasonable. Most crash analytics systems (including Firebase Crashlytics and Unity's own Cloud Diagnostics) include a configurable number of the most recent logs in a crash report, and frankly I can't imagine trying to debug a crash report without logs. I know that log messages are expensive in that some heap garbage must be allocated (at least the log message string itself, but possibly other things depending on what's logged) and persisted on disk (for desktop platforms anyway), but this could be a small fraction of the other garbage getting allocated in a frame, and well worth it for the ability to debug crashes.

    TL;DR Wouldn't "removing the performance and memory impact of logs in release builds" be undesirable, from a maintenance/support perspective?
     
  10. VoxelMatt

    VoxelMatt

    Joined:
    Apr 22, 2015
    Posts:
    42
    Currently the _entire_ UnityServices is effectively un-initialised until the player comes online. I just want the game to boot and for someone to be able to play the game. Obviously I don't expect ads or analytics or login services to work.... but I expect them to be Initialised! All those services function correctly after the player has been online and then later loses their connection. Analytics get queued, etc. So why can't that all happen when the player boots offline as well?
     
  11. Rabadash8820

    Rabadash8820

    Joined:
    Aug 20, 2015
    Posts:
    94
    I'll also add that we're unable to access
    AuthenticationService.Instance
    until after
    UnityServices.InitializeAsync
    has been called, which is quite annoying when all I want to do is register some signin event handlers...