Search Unity

Are custom worlds broken or no longer supported?

Discussion in 'Entity Component System' started by Sibz9000, Mar 24, 2019.

  1. Sibz9000

    Sibz9000

    Joined:
    Feb 24, 2018
    Posts:
    149
    Right here's a working example. It's all a bit confusing, and very likely to change in future releases for that reason.
    Code (CSharp):
    1. [AlwaysUpdateSystem]
    2. public class MyCS : JobComponentSystem, IMyInterface
    3. {
    4.     protected override JobHandle OnUpdate(JobHandle inputDeps)
    5.     {
    6.         Debug.Log("Is Running");
    7.         return inputDeps;
    8.     }
    9.     protected override void OnCreate()
    10.     {
    11.     }
    12. }
    13.  
    14. interface IMyInterface { }
    15.  
    16. public class Bootstrap : ICustomBootstrap
    17. {
    18.     public List<Type> Initialize(List<Type> systems)
    19.     {
    20.         // Get a list of systems with interface
    21.         var systemsWithInterface = systems
    22.             // Where type has any interface with name of my interface
    23.             .Where(type => type.GetInterfaces().Any(iface => iface.Name == nameof(IMyInterface)))
    24.             .ToList();
    25.  
    26.         // Remove from default systems list so they are not created in default world
    27.         systems.RemoveAll(type => systemsWithInterface.Contains(type));
    28.  
    29.         // Create our world
    30.         var MyWorld = new World("World with systems that have IMyInterface");
    31.  
    32.         // To Change 'Default world'
    33.         // `World.Active = MyWorld`
    34.  
    35.         // Update player loop
    36.         // `ScriptBehaviourUpdateOrder.c(MyWorld);`
    37.         // NB this moves the default systems to this world,
    38.         // but they are moved to default world again if you return anything but null from this method
    39.         // So call UpdatePlayerLoop if you want your world to be the default world
    40.         // and host the default systems and be automatically updated
    41.         // (and remember to return null from this method)
    42.  
    43.         // If not changing default world
    44.         // World.Active is intialized with 'shared' default systems here
    45.         ScriptBehaviourUpdateOrder.UpdatePlayerLoop(World.Active);
    46.  
    47.         // We must use 'shared' default systems
    48.         var simGroup = World.Active.GetExistingSystem<SimulationSystemGroup>();
    49.  
    50.         // Add systems
    51.         foreach (var type in systemsWithInterface)
    52.         {
    53.             var system = MyWorld.CreateSystem(type);
    54.             // If you want to support [UpdateInGroup] you need to do reflection
    55.             // and add to correct group here.
    56.             simGroup.AddSystemToUpdateList(system);
    57.             simGroup.SortSystemUpdateList();
    58.         }
    59.  
    60.         // Return systems for default world
    61.         // Return null if you changed the default world
    62.         return systems;
    63.     }
    64. }
    65.  
     
    Last edited: Apr 21, 2019
  2. Piefayth

    Piefayth

    Joined:
    Feb 7, 2017
    Posts:
    61
    Ahh, I get the approach now. I was missing the fact that UpdateBefore/After are processed in SortSystemUpdateList, which, of course, makes sense in retrospect.

    My criticism here is, aren't you just repeating the work that DefaultWorldInitilization would do for you? You can get the same effect using it to create your world, AND each world then gets a unique CustomBootstrap Initialize call during which you can filter your systems. Plus it should automatically support UpdateInGroup.
     
    Sibz9000 and Deleted User like this.
  3. Sibz9000

    Sibz9000

    Joined:
    Feb 24, 2018
    Posts:
    149
    I think you are right. There was a reason I didn't use DefaultWorldInitialization to begin with, I first started with that, but something made me go for this alternative approach. but I can't rebember now what it was. I'm going to try it and see what happens.
     
  4. Sibz9000

    Sibz9000

    Joined:
    Feb 24, 2018
    Posts:
    149
    Ah yes, For the purposes of automatically populating worlds, DefaultWorldInitialization only populates the last world.
    Given the example below, the default world is empty and DefaultWorldSystem does not update.
    So while I repeat what DefaultWorldInitialization does, this is the only way I can get two worlds that are hooked up to the Initialization/Simulation/Presentation update groups.

    If that's not necessary, and you don't mind not seeing systems in the entitydebugger. You can just add systems to a world and manually call update.

    Note UNITY_DISABLE_AUTOMATIC_SYSTEM_BOOTSTRAP is defined hence I Initialize the "Default World" myself in this example.
    Code (CSharp):
    1. public class Bootstrap : ICustomBootstrap
    2. {
    3.     [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)]
    4.     public static void Init()
    5.     {
    6.  
    7.         DefaultWorldInitialization.Initialize("Default World", false);
    8.         DefaultWorldInitialization.Initialize("Test World", false);
    9.     }
    10.  
    11.     public List<Type> Initialize(List<Type> systems)
    12.     {
    13.         if (World.Active.Name == "Test World")
    14.         {
    15.             systems.Remove(typeof(DefaultWorldSystem));
    16.             return systems;
    17.         }
    18.         systems.Remove(typeof(CustomWorldSystem));
    19.         return systems;
    20.     }
    21. }
    22.  
    23. public class CustomWorldSystem : ComponentSystem
    24. {
    25.     protected override void OnUpdate()
    26.     {
    27.  
    28.     }
    29. }
    30.  
    31. public class DefaultWorldSystem : ComponentSystem
    32. {
    33.     protected override void OnUpdate()
    34.     {
    35.  
    36.     }
    37. }
     
  5. drhodor

    drhodor

    Joined:
    Aug 18, 2013
    Posts:
    39
    What are the best ways to filter systems between worlds? I am trying to get just what I need to run Unity Physics into a custom world, but none of the other stuff that comes from a Default World Initialization.
     
  6. Sibz9000

    Sibz9000

    Joined:
    Feb 24, 2018
    Posts:
    149
    For separating Unity.Physics system groups, a guess would be to filter on that namespace. But I do not know if there are other systems outside that name space that may be dependent on.
    If you used
    DefaultWorldInitialization.Initialize("MyPhysicsWorld", false);

    you could use the code below. Be aware that calling DefaultWorldInitialization.Initialize may have unintended consequences for the default systems. You may want to call
    DefaultWorldInitialization.Initialize("Default World", false);
    after, but that may muck up how the physics systems update.
    Note: this may not actually work as intended, but shows how to filter on namespace.
    Code (CSharp):
    1.     public List<Type> Initialize(List<Type> systems)
    2.     {
    3.         var physicsSystems = systems.Where(type => type.Namespace != null && type.Namespace.StartsWith("Unity.Physics")).ToList();
    4.         if (World.Active.Name == "MyPhysicsWorld")
    5.         {
    6.             return physicsSystems;
    7.  
    8.         }
    9.         systems.RemoveAll(type => physicsSystems.Contains(type));
    10.         return systems;
    11.     }

    If you want to use https://github.com/Sibz/CustomWorldBootstrap then the following should work:
    Code (CSharp):
    1. public class Bootstrap : CustomWorldBootstrap
    2. {
    3.     public Bootstrap()
    4.     {
    5.         WorldOptions.Add(new WorldOption("My Physics World")
    6.         {
    7.             CustomIncludeQuery = (systems) => systems.Where(type => type.Namespace != null && type.Namespace.StartsWith("Unity.Physics")).ToList()
    8.         });
    9.     }
    10. }
    NB: this will update the systems in their intended groups and hopefully work without an issue, however I have not worked with the Unity.Physics namespace so can not be sure that this is all you need to do to isolate physics into it's own world.

    edit: added null check to namespace
     
    Last edited: Apr 23, 2019
  7. Sibz9000

    Sibz9000

    Joined:
    Feb 24, 2018
    Posts:
    149
    Just tested with CustomWorldBootstrap, it works as far as setting up the systems goes, haven't tested any actual physics in world.
    There's one warning though:
     
  8. spectre1989

    spectre1989

    Joined:
    Oct 6, 2009
    Posts:
    125
    Reading system_update_order.md it sounds like the recommended way to do multiple worlds is to create the component system groups in the custom worlds, create the systems in the custom worlds and add them to their groups. Then you add the groups from the custom worlds to the default world groups, but when I do that, I get warnings like:

    So is the documentation outdated? Do I need to either update the custom world systems via MonoBehaviours, or maybe modify the player loop after the default world has initialised?
     
  9. Sibz9000

    Sibz9000

    Joined:
    Feb 24, 2018
    Posts:
    149
    That error suggests you're adding a
    InitializationSystemGroup 
    to a
    InitializationSystemGroup
    which shouldn't be done.

    To add a system to a second world, use
    customWorld.CreateSystem<MySystem>()


    If you need it to update in the
    InitializationSystemGroup
    then
    defaultWorld.GetOrCreateSystem<InitializationSystemGroup>().AddSystemToUpdateList(mySystem)

    Default world is what ever world has the default systems (usually you can just use
    World
    )

    Then I believe you need to call
    SortSystemUpdateList() 
    on the
    InitializationSystemGroup
    to apply any UpdateBefore/UpdateAfter ordering.
     
  10. spectre1989

    spectre1989

    Joined:
    Oct 6, 2009
    Posts:
    125
    Yeah I was following the instructions in system_update_order.md:
    In any case, I also tried adding my custom world's systems to the groups in the default world, and I get the same warning, e.g:
     
    Last edited: Nov 20, 2019
  11. Deleted User

    Deleted User

    Guest

    You might want to use:
    https://github.com/Knightmore/MultiWorldBootstrap
     
    Sibz9000 likes this.
  12. spectre1989

    spectre1989

    Joined:
    Oct 6, 2009
    Posts:
    125
    Yeah so look, this adds the custom world groups to the default world groups which @Sibz9000 said shouldn't be done, and also generates the same error:
    Code (CSharp):
    1. World.Active.GetOrCreateSystem<InitializationSystemGroup>().AddSystemToUpdateList(customWorld.World.GetOrCreateSystem<InitializationSystemGroup>());
    2.             World.Active.GetOrCreateSystem<SimulationSystemGroup>().AddSystemToUpdateList(customWorld.World.GetOrCreateSystem<SimulationSystemGroup>());
    3.             World.Active.GetOrCreateSystem<PresentationSystemGroup>().AddSystemToUpdateList(customWorld.World.GetOrCreateSystem<PresentationSystemGroup>());
    I'll try it out later when I have some time, but I'm 90% sure this doesn't work.
     
  13. spectre1989

    spectre1989

    Joined:
    Oct 6, 2009
    Posts:
    125
  14. Deleted User

    Deleted User

    Guest

    Yeah the warnings are subject to be ignored. Even some Unity samples contain them afaik.
     
  15. spectre1989

    spectre1989

    Joined:
    Oct 6, 2009
    Posts:
    125
    In the intervening time I've just manually inserted my custom world's groups into the player loop, which also works and doesn't generate warnings. I really hope the update to the multiplayer repo happens soon and addresses all this multiworld nonsense.
     
    Sibz9000 likes this.