Search Unity

  1. Unity Asset Manager is now available in public beta. Try it out now and join the conversation here in the forums.
    Dismiss Notice
  2. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  3. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

How to pass data into SceneService.LoadSceneAsync() ?

Discussion in 'Project Tiny' started by furroy, Jun 6, 2019.

  1. furroy

    furroy

    Joined:
    Feb 24, 2017
    Posts:
    93
    The spawning in the Spawn demo seems kind of hacky to spawn in bullets and then look for ships that asked for a bullet and randomly align a bullet to each ship found. How can I directly pass in data to the spawned entity? Alternatively can I save the SceneData returned and stuff that into a hash table along with the data it needs and then during the "init" process, refer to the hash table to get the associated data?
     
  2. AlexMasse

    AlexMasse

    Joined:
    Jun 29, 2014
    Posts:
    19
    The LoadSceneAsync() method returns an entity that has a Unity.Tiny.Scenes.SceneData component. So yes, you could cache that entity somewhere along with some data. Then, every frame, loop all entities that have not been initialized, find the corresponding SceneData and its data to assign, set the data and set that entity as initialized with a tag component or bool field.

    It might not follow all best practices but here's a script that does that:

    Code (CSharp):
    1. using System.Collections.Generic;
    2. using Unity.Entities;
    3. using Unity.Mathematics;
    4. using Unity.Tiny.Core;
    5. using Unity.Tiny.Core2D;
    6. using Unity.Tiny.Scenes;
    7.  
    8.     public class LoadAndInitSceneSystem : ComponentSystem
    9.     {
    10.         public static List<SceneToLoadAndInit> SceneToInit = new List<SceneToLoadAndInit>();
    11.  
    12.         protected override void OnUpdate()
    13.         {
    14.             for (int i = 0; i < SceneToInit.Count; i++)
    15.             {
    16.                 // Spawn (load) the scene if it was not loaded yet
    17.                 var sceneToInit = SceneToInit[i];
    18.                 if (!sceneToInit.HasStartedLoading)
    19.                 {
    20.                     var sceneEntity = SceneService.LoadSceneAsync(sceneToInit.SceneReference);
    21.                     sceneToInit.SceneEntity = sceneEntity;
    22.                     sceneToInit.HasStartedLoading = true;
    23.                     SceneToInit[i] = sceneToInit;
    24.                     continue;
    25.                 }
    26.  
    27.                 // Init the scene once it's loaded
    28.                 var sceneData = EntityManager.GetComponentData<Unity.Tiny.Scenes.SceneData>(sceneToInit.SceneEntity);
    29.                 if (sceneData.Status == SceneStatus.Loaded)
    30.                 {
    31.                     Entities.WithAll<AsyncSceneLoading>().ForEach((Entity entity, ref Translation translation) =>
    32.                     {
    33.                         var sceneGuid = EntityManager.GetSharedComponentData<SceneGuid>(entity);
    34.                         var sceneInstance = EntityManager.GetSharedComponentData<SceneInstanceId>(entity);
    35.                         if (sceneGuid == sceneData.Scene.SceneGuid && sceneInstance.InstanceId == sceneData.Scene.SceneInstanceId.InstanceId)
    36.                         {
    37.                             translation.Value = new float3(sceneToInit.Position.x, sceneToInit.Position.y, 0f);
    38.  
    39.                             PostUpdateCommands.RemoveComponent<AsyncSceneLoading>(entity);
    40.  
    41.                             SceneToInit.RemoveAt(i);
    42.                             i--;
    43.                         }
    44.                     });
    45.                 }
    46.             }
    47.         }
    48.     }
    49.  
    50.     public struct SceneToLoadAndInit
    51.     {
    52.         public SceneReference SceneReference;
    53.         public bool HasStartedLoading;
    54.         public Entity SceneEntity;
    55.         public float2 Position;
    56.     }
    57.  
    58.     public struct AsyncSceneLoading : IComponentData
    59.     {
    60.  
    61.     }
    62.  

    When I want to spawn something at a position, I just add it to the list like so:

    Code (CSharp):
    1. var mySceneReference = World.TinyEnvironment().GetConfigData<GameScenesConfiguration>().MySceneReference;
    2. LoadAndInitSceneSystem.SceneToInit.Add(new SceneToLoadAndInit() {
    3.         SceneReference = mySceneReference,
    4.         Position = myPosition
    5. });
    Just add the AsyncSceneLoading component to the entity that has the Components you want to modify in your Scene. AsyncSceneLoading will be removed once the scene has been initialized.
     
    Last edited: Jun 6, 2019
  3. Dunk86

    Dunk86

    Joined:
    May 10, 2015
    Posts:
    53
    I was hitting against this problem too - if I remember correctly, pre-C# I could spawn objects synchronously then set data directly. Gnome's method above is a nice workaround, but it's limited to setting the fields manually handled (i.e. position).
    I feel like we're missing something obvious here - perhaps there's a part of the DOTs interface that handles object creation and setup that isn't in the Tiny API yet?
     
  4. furroy

    furroy

    Joined:
    Feb 24, 2017
    Posts:
    93
    i got this working for the simplest cases where my scene/entity group/whatever they are called, is just a sprite. but when i make them contain an empty entity child w/ the AsyncSceneLoadingTag and then other sprite children under that, the LoadAndInitSceneSystem.OnUpdate() is never finding them to initialize.