Search Unity

  1. Get the latest news, tutorials and offers directly to your inbox with our newsletters. Sign up now.
    Dismiss Notice

HasSingleton Crashes When Called From Interop.

Discussion in 'Project Tiny' started by silverduck, Mar 3, 2021.

  1. silverduck

    silverduck

    Joined:
    May 16, 2010
    Posts:
    27
    I'm baffled by this. I've been working on a Tiny multiplayer web-browser game using websockets. As per the guidance of the Getting Started document, I set up an interop callback function to be called with updates from the server

    Code (CSharp):
    1. public void OnServerUpdate(TinyJsonArray serverData)
    2.         {
    3.             UnityEngine.Debug.Log("EnemyManager OnServerUpdate");          
    4.             if (serverData.Length==0 || (PlayerMoveSystem.m_PlayerExists==false))
    5.             {
    6.                 return;
    7.             }
    8.             currentLatency = timeOfLastUpdate - Time.ElapsedTime;
    9.  
    10.             Debug.Log("server update 1");
    11.            
    12.             var player = GetSingleton<Player>();
    13.             Debug.Log("server update 1");
    14.             var playerId = player.id;
    15. ....
    What's wild though is that it seems as though calling HasSingleton<>() or GetSingleton<>() for almost any singleton component causes the game to crash. When it does so I get the following runtime error and it seems the most helpful message is simply. "failed to allocate"

    Code (CSharp):
    1. [Log] [libil2cpp] A managed exception was thrown. The Tiny runtime does not support managed exceptions. (8b209c5c-1dbf-4abc-843c-29608185f96d, line 25)
    2. [Log] [libil2cpp] The exception message is: failed to allocate (8b209c5c-1dbf-4abc-843c-29608185f96d, line 25)
    3. [Log] [libil2cpp] No managed stack trace exists. Make sure this is a development build to enable managed stack traces. (8b209c5c-1dbf-4abc-843c-29608185f96d, line 25)
    4. [Log] [libil2cpp] No native stack trace exists. Make sure this is platform supports native stack traces. (8b209c5c-1dbf-4abc-843c-29608185f96d, line 25)

    I say "ALMOST" any Singleton because when I tested HasSingleton<>() with a few other Components instead of Player, they all seemed to fail except for one called GameState, which only has a single enum property.

    To be clear...

    Calling HasSingleton<>() on the same singletons at the same part in the game but from OnUpdate causes no problems. Also, it doesn't matter if the Singletons actually exist or not at the time of the call.

    I feel this is a very reasonable use case for an interop callback. If this is somehow expected behavior I would feel very silly using the call back to simply set a bool saying it's time to poll the interop in OnUpdate to get the data.
     
  2. AbdulAlgharbi

    AbdulAlgharbi

    Unity Technologies

    Joined:
    Jul 27, 2018
    Posts:
    319
    Make sure the entity or the scene that has the singleton is loaded
    I always recommend adding
    RequireSingletonForUpdate to your system and when the system is actually running get the singleton
     
  3. silverduck

    silverduck

    Joined:
    May 16, 2010
    Posts:
    27
    I have made entirely sure that the singleton is loaded. Calling HasSingleton<>() from OnUpdate (whether or not the Singleton is loaded) causes no problems. It is only a problem when I call it from my Interop Callback method. Even then, I've delayed the call back by 10 seconds (to when the Player singleton DEFINITELY exists), and it still causes a crash. Regardless, HasSingleton shouldn't crash when it's just supposed to return a false.

    To reiterated, I don't think RequireSingletonForUpdate is relevant here because this is not happening in OnUpdate. It is happening in a function that is called from javascript outside of Unity.

    I apologize for my script showing "GetSingleton" but I assure you the problem I'm describing exists with both HasSingleton and GetSingleton, EVEN when the Singleton is currently loaded.
     
  4. silverduck

    silverduck

    Joined:
    May 16, 2010
    Posts:
    27
    Now that I've simplified OnServerUpdate so that it just saves the TinyJsonArray to a class property to be used later in OnUpdate, I'm running into a new issue. It seems like what I'm doing is just saving a reference to the TinyJsonArray that's being passed from Interop. This is a temporary variable though. So when I try to use it in OnUpdate it's deallocated. How can I make a Deep Copy of my TinyJsonArray? Do I need to for loop through all of its elements and append them to a new Array to copy them over? am I misunderstanding something in genera? Here is my code of what I've turned OnServerUpdate into (to avoid HasSingleton not working in this context).

    Code (CSharp):
    1. private bool enemyDataIsReady = false;
    2. private TinyJsonArray enemyDataJson;
    3.  
    4. public void OnServerUpdate(TinyJsonArray serverData)
    5.         {
    6.             enemyDataIsReady = true;
    7.             enemyDataJson = new TinyJsonArray();
    8.             enemyDataJson = serverData;  
    9.         }
     
  5. djsell

    djsell

    Joined:
    Aug 29, 2013
    Posts:
    59
  6. ben-rasooli

    ben-rasooli

    Joined:
    May 1, 2014
    Posts:
    40
    I was getting a similar error with TinyJsonInterface. My issue was resolved when I change from
    Code (CSharp):
    1. TinyJsonInterface jsonData = new TinyJsonInterface(
    2.             data,
    3.             Unity.Collections.Allocator.Temp);
    to
    Code (CSharp):
    1. TinyJsonInterface jsonData = new TinyJsonInterface(
    2.             data,
    3.             Unity.Collections.Allocator.Persistent);
     
    SINePrime likes this.
unityunity