Search Unity

Are custom worlds broken or no longer supported?

Discussion in 'Data Oriented Technology Stack' started by Sibz9000, Mar 24, 2019.

  1. Sibz9000

    Sibz9000

    Joined:
    Feb 24, 2018
    Posts:
    80
    I am unable to get a custom world to work.

    I have a monobehaviour, in the start method, I call:

    Code (CSharp):
    1. m_World = new World("MyWorld");
    2. m_World.GetOrCreateManager<MySystemGroup>();
    3.  
    4. // Was hoping this wasn't necessary as it's in MySystemGroup
    5. m_World.GetOrCreateManager<MySystem>();
    6.  
    7. ScriptBehaviourUpdateOrder.UpdatePlayerLoop(m_World);
    The world shows up in entity debugger, but the system group and system does not.
    The System and System Group is Decorated with [DisableAutoCreation].

    If I remove the decorators and my custom world initialisation, it all works in the default world.
     
    Antypodish likes this.
  2. Draveler

    Draveler

    Joined:
    Jul 1, 2018
    Posts:
    62
    TZ- and Sibz9000 like this.
  3. Sibz9000

    Sibz9000

    Joined:
    Feb 24, 2018
    Posts:
    80
    Thanks, missed that in the release notes, doh!
     
  4. Sibz9000

    Sibz9000

    Joined:
    Feb 24, 2018
    Posts:
    80
    Yup, I think they're broken as mentioned in that thread. I can't get it to add systems to the playerloop for any world but the last world created with
    DefaultWorldInitialization.Initialize

    I am filtering in the ICustomBootstrap Initialize method, but only the systems for the last world are actually in the playerloop. Though I did notice they do get created in their respective worlds, so is possible to manually run the update.

    I'll work around it but hopefully the next release addresses this issue.
     
  5. drhodor

    drhodor

    Joined:
    Aug 18, 2013
    Posts:
    20
    Custom Worlds are not working at all for me right now -- which I discovered while out the new Unity Physics in several worlds at once. Adding registered physics entities does nothing (and neither does adding anything not-physics!).

    The UNITY_DISABLE_AUTOMATIC_SYSTEM_BOOTSTRAP define still "works," however -- it will prevent the creation of the World.Active. However, custom worlds that you create subsequently will not work, even when I assigned to World.Active.
     
  6. TZ-

    TZ-

    Joined:
    Oct 23, 2017
    Posts:
    26
    I have got a custom world along with the default world, but my problems so far are

    EntityDebugger does not show that worlds system inside it, instead it lists them in their group, but within Default World's SimulationSystemGroup

    that said, the first system in the custom worlds' group, does create all the entities it is supposed to be creating, in its custom world, i can see those entities in the EntityDebugger when set to the custom world drop down

    in the second system of that group, i am attempting to use chunk iteration to go over those entities and do some work on them, but it fetches matching entities from the DefaultWorld and not its own world, it then attempts to do the tasks it is set, but ofc to the wrong entity.

    now maybe there is some trick to getting chunks out of a custom world to iterate over but so far i have not been able to find it, if anyone can advise it would be much appreciated.

    I did try using the ICustomBootstrap, but that just resulted in the Default World being empty, and everything set to my custom world

    guessing by comments here and in other threads, this was probably not a good time to be trying to learn how to create a custom world for my generation.
     
  7. Sibz9000

    Sibz9000

    Joined:
    Feb 24, 2018
    Posts:
    80
    My sentiments exactly. I will get back to using multiple worlds later when it works.

    For now I use custom worlds, and just create the one I am using, last, so it works.
    I use the first custom world I create to move entities to for serialisation, so no systems are running anyway.
     
  8. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    1,265
    ScriptBehaviourUpdateOrder.UpdatePlayerLoop is now hardcoded to specifically looking for 3 update groups (simulation/presentation/init) so if your world didn't has these 3 specific group they will not be run by player loop. The new player loop know only how to run these 3 groups in order.

    So you either want to make your world with that 3 groups or use the default world but add your systems to existing 3 groups group.AddSystemToUpdateList(__); ->
    group.SortSystemUpdateList(); You can also add your own group within one of 3 groups.

    The new system has the default world tied to so many places, such as ConvertToEntity that relies on World.Active. I think using UNITY_DISABLE_AUTOMATIC_SYSTEM_BOOTSTRAP is very risky of breaking sooner or later as long as we are still in preview phase.
     
    Sibz9000 likes this.
  9. TZ-

    TZ-

    Joined:
    Oct 23, 2017
    Posts:
    26
    From my reading, i decided i did not want to go down the route of having all custom worlds and disabling the default one, i just want to be able to have a seperate world doing the generation before moving entities to the defaultworld in which the game will be once they are ready.

    My systems are being put into their own updategroup, in the default world simulation group, so they are running and the first system is correctly creating the entities in the custom world.

    The thing i am having problems with is, how to get the entities in the custom world into subsequent systems so that more work can be done to them.

    Standard chunk iteration is getting the entities that match the query but are in the default world not the custom world.

    is there a setting somewhere that you can assign which world it should be populating the componentGroup from?
     
  10. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    1,265
    Use EntityManager.MoveEntitiesFrom ?

    The setting is that query, the query requires either EntityManager or ComponentGroup, if EntityManager, it is already a 1 per world object so it work on Entity on that world. If ComponentGroup, they must be get from either EntityManager or GetComponentGroup which is a protected method of a system, which must currently in a World. So they all related to the current world of either your system or EntityManager.
     
  11. TZ-

    TZ-

    Joined:
    Oct 23, 2017
    Posts:
    26
    Use EntityManager.MoveEntitiesFrom ?

    either i am not explaining myself well or i have the wrong idea about custom worlds

    my idea of custom world from things i have read

    make custom world
    it has own systems and entity manager
    in those systems, create entities,
    then over many systems do a lot of work on those entities,
    once entities are finished and ready, then use EntityManager.MoveEntities.........


    i have system1 creating entities in custom world

    system2 cannot see them, i do not want to get them to send them yet, they are just entities with a few components on, i need to do alot of work on them, before they are ready to go to default world.

    but i do not know how to tell system2 which world to look in when it tries to get entities already created, that it needs to do some work on

    i have spent some more time reading, and i am now wondering is custom world is only for create/destroy entities, and not for create/modify/send to default.

    you say it is either componentsystem or entitymanager for the query

    this is the only way i know how to do query, i dont know how to give it the custom entity manager
    EntityArchetypeQuery sectorRangeCheckQuery = new EntityArchetypeQuery
    {
    All = new ComponentType[] { typeof(Sector) }
    };
    sectorRangeCheckGroup = GetComponentGroup(sectorRangeCheckQuery);
     
    Antypodish likes this.
  12. Sibz9000

    Sibz9000

    Joined:
    Feb 24, 2018
    Posts:
    80
    How do we do this? If I filter the system list in ICustomBootstrap to only include those three groups, it doesn't show anything in the entity debugger for that world.

    I wrote a quick test:
    Code (CSharp):
    1. DefaultWorldInitialization.Initialize("SettingsWorld", false);
    2. DefaultWorldInitialization.Initialize("MainWorld", false);
    Code (CSharp):
    1. class Bootstrap : ICustomBootstrap
    2.     {
    3.         public List<Type> Initialize(List<Type> systems)
    4.         {
    5.             if (World.Active.Name == "MainWorld")
    6.             {
    7.                 return systems.Where(x =>
    8.               !x.Name.Contains("MySystemGroup1")
    9.               ).ToList();
    10.                 // return systems;
    11.             }
    12.             else // World is default or SettingsWorld
    13.             {
    14.                 return systems.Where(x =>
    15.                 x.Name.Contains("SimulationSystemGroup")
    16.                 ||
    17.                 x.Name.Contains("MySystemGroup1")
    18.                 ).ToList();// new List<Type>();
    19.             }
    20.         }
    21.     }
    22.     [UpdateInGroup(typeof(SimulationSystemGroup))]
    23.     public class MySystemGroup1 : ComponentSystemGroup
    24.     {
    25.  
    26.     }
    27.     [UpdateInGroup(typeof(MySystemGroup1))]
    28.     public class MyComponentSystem : ComponentSystem
    29.     {
    30.  
    31.         protected override void OnUpdate()
    32.         {
    33.             EntityManager.CreateEntity();
    34.             Debug.LogFormat("Created entity in world {0}", World.Name);
    35.         }
    36.     }

    The result is nothing ... the system does not run.
     
  13. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    436
    Which world did you use to create system2 with? If you Debug.Log system1's world name and system2's world name (world is a property of ComponentSystem and JobComponentSystem), do they match?

    DefaultWorldInitialization.Initialize gets a list of systems to instantiate for that world, automatically assigns them to the groups they belong to, sets that world as active, and then overwrites the player loop to use the Initialization, Simulation, and Presentation system groups belonging to that world (it creates those groups regardless of whether or not you specify them in the returned list).
     
    TZ- likes this.
  14. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    1,265
    Check out system_update_order.md in the package folder on "Multiple Worlds" section. In this interface `systems` is all the systems reflected from all C# assemblies. The meaning of List<Type> returned from this is the member of default world to be created next, sorted into an appropriate 3 top level groups, to be created later as well. So in this moment you have just systems. No 3 basic groups, no worlds. Your check for SimulationSystemGroup will be for nothing.

    To implement multiple world in this interface, you could new your own World right here, create 3 basic groups manually (or any group if you are not planning to run it in a player loop), and choose some systems from the input argument or hard code a typeof class to add into those groups. To return empty list or not is an another matter if you want default world to be created or not.
     
    Sibz9000 likes this.
  15. TZ-

    TZ-

    Joined:
    Oct 23, 2017
    Posts:
    26
    thanks for this, it got me looking in the right direction :D

    it turned out i had had confusion regarding a line World.Active = world;

    I did not think that it was adding to, but replacing, thinking it was going to change the World.Active to be my new world and not the default one

    (i had seen this line in an example that was not retaining the defaultWorld, and thought that was what you did if you were not going to use the defaultWorld)

    so i do now have both systems showing world to be the correct custom one, and they are in a group that has its update called from a sytem in default world.

    System2 is now seeing and getting the right entities :D
    Now i need to research moving the entities when ready to the default world....

    thanks again!!
     
  16. Sibz9000

    Sibz9000

    Joined:
    Feb 24, 2018
    Posts:
    80
    Not sure on where this is.
     
  17. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    436
    That's what it does. But Unity's default initialization functions will also set World.Active and the playerloop only knows the most recent world that configured the playerloop.
     
    TZ- likes this.
  18. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    1,265
    In Library/PackageCache you can find your UPM packages. Then look in Documentation~ folder.
     
    Sibz9000 likes this.
  19. drhodor

    drhodor

    Joined:
    Aug 18, 2013
    Posts:
    20
    You're right that it definitely needs to be fixed to get multiple custom worlds to support physics :)
     
  20. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    5,411
    I haven't been touching worlds so far.
    Now, I try to follow what is posted here. Is my understanding correct, that current custom worlds mechanics is still broken?
    So far seams, I got same issue as per OP post and got trouble to deduct right solution, to keep multiple active worlds, as I want read data from multiple groups, using GetComponentGroup.

    I looked provided links, but nothing seams certain. Or maybe better, as few others mentioned, to wait until proper solution will be provided? Are any samples at current, using multi wolds mechanics?

    Edit:
    I searched for wold key word, but no avail.
    https://github.com/Unity-Technologi...emSamples/search?p=1&q=world&unscoped_q=world
     
    Last edited: Apr 7, 2019
  21. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    1,428
    Custom worlds works fine in my case, look here:
    https://docs.unity3d.com/Packages/com.unity.entities@0.0/manual/system_update_order.html
    Especially in Multiple Worlds
     
    Antypodish likes this.
  22. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    5,411
    Oh good.
    I looked previously into this documentation, but haven't looked into System Update Order section. Many thanks.
     
  23. drhodor

    drhodor

    Joined:
    Aug 18, 2013
    Posts:
    20
    Did you get multiple worlds working?
     
  24. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    5,411
    I haven't yet, since I need update entities package. And I don't won't to update yet, untill I finish current mechanics that I am working on.

    Most likely I will build separate project as a template.
     
  25. Sibz9000

    Sibz9000

    Joined:
    Feb 24, 2018
    Posts:
    80
    I have got it working, even made a handy CustomWorldBootstrap class so all you need is `[CreateInWorld("World Name")]` attribute to create world and put tagged systems in it.
    https://github.com/Sibz/CustomWorldBootstrap
    It's fresh off the press and not fully tested, but give it a whirl and get back to me on the repo with any issues. The readme should explain usage pretty well.
    * Works with Entities preview.30
     
    wobes and Antypodish like this.
  26. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    5,411
    In https://github.com/Sibz/CustomWorldBootstrap
    You have
    Code (CSharp):
    1. public class MyBootstrap : CustomWorldBootstrap
    2. {
    3.     public MyBootstrap()
    4.     {
    5.         WorldOptions.Add(new WorldOption("My world with initialise callback") { OnInitialize = OnMyWorldInitialise});
    6.     }
    7.  
    8.     public OnMyWorldInitialise(World world)
    9.     {
    10.         // Do stuff once when all systems have been created.
    11.     }
    12. }
    OnMyWorldInitialise is highlighted red.
    I wonder, did you forgot add OnMyWorldInitialise to CustomWorldBootstrap, or I got missing something?
     
  27. Sibz9000

    Sibz9000

    Joined:
    Feb 24, 2018
    Posts:
    80
    oops forgot a void there

    Code (CSharp):
    1. public class MyBootstrap : CustomWorldBootstrap
    2. {
    3.    public MyBootstrap()
    4.    {
    5.        WorldOptions.Add(new WorldOption("My world with initialise callback") { OnInitialize = OnMyWorldInitialise});
    6.    }
    7.  
    8.    public void OnMyWorldInitialise(World world)
    9.    {
    10.        // Do stuff once when all systems have been created.
    11.    }
    12. }
     
    Antypodish likes this.
  28. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    5,411
    I was thinking the same (I should have checked), but I have get suggested with public MyBootstrap(), which as well doesn't have void.

    Isn't public MyBootstrap (), a method as well?

    Edit:
    I haven't fully dive in into CustomWorldButsrap.cs, but I am curious, how did you derived all that code. Seams a bit verbose, yet it works. :)

    Edit2:
    Does it have to really use linq, wonder? :rolleyes:
     
    Last edited: Apr 8, 2019
  29. Sibz9000

    Sibz9000

    Joined:
    Feb 24, 2018
    Posts:
    80
    public MyBootstrap is a constructor, has no type.

    tbh I just made it up as a went along :D I mean to refactor it, but not enough time in a day.

    probably not. but as it doesn't need to be performant, it doesn't matter. just makes it so much easier.
     
  30. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    5,411
    That is fine, thx for sharing anyway.

    One more thing, to keep bothering you :p

    Where LoadingWorld0 to LoadingWorld3 came from?

    upload_2019-4-8_14-17-19.png

    I am blind enough, to not see LoadingWorld in any of scripts.
    I can add systems and entities to them just fine.
    I feel a bit magic going on there.

    I got impression, is this side effect / unintentional ?
     
  31. Sibz9000

    Sibz9000

    Joined:
    Feb 24, 2018
    Posts:
    80
    Loading worlds came from a recent entities update ... they just appeared, I have no explanation for that. I just pretend they don't exist.
     
  32. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    5,411
    Fair enough.
    Maybe summoning Unity officials, i.e. @Joachim_Ante, or who more relevant, which could cast some light on the topic?
     
  33. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    1,428
    Loading Worlds is part of SubScene streaming logic. SubScenes loads in this worlds by ExclusiveEntityTransaction, which mean this creation not block main thread and can run asynch (but it blocks main thread when you call MoveEntitiesFrom, but anyway it's faster than create\destroy\edit entities on main thread).
    Just look at: \Library\PackageCache\com.unity.entities@0.0.12-preview.30\Unity.Scenes.Hybrid\SubSceneStreamingSystem.cs
     
    Last edited: Apr 8, 2019
    Sibz9000 likes this.
  34. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    5,411
    Ah here we go

    Code (CSharp):
    1. void CreateStreamWorld(int index)
    2.         {
    3.             m_Streams[index].World = new World("LoadingWorld" + index);
    4.         }
    Then there is
    Code (CSharp):
    1.  
    2. const int LoadScenesPerFrame = 4;
    3. ...
    4. protected override void OnCreate()
    5.         {
    6.             for (int i = 0; i < LoadScenesPerFrame; ++i)
    7.                 CreateStreamWorld(i);
    8. ...
    9.  
    Thx bunch for an explanation.
     
  35. Sibz9000

    Sibz9000

    Joined:
    Feb 24, 2018
    Posts:
    80
  36. wobes

    wobes

    Joined:
    Mar 9, 2013
    Posts:
    669
    Any ideas how to initialize a world based on Interface of a system? Client world: IClientSystem, Server world: IServerSystem.
     
  37. Piefayth

    Piefayth

    Joined:
    Feb 7, 2017
    Posts:
    58
    Haven't tried, but I assume you can do this by calling the two-argument "GetInterface" on each type in ICustomBootstrap to check if each has a specific interface, then remove them as necessary.
     
  38. wobes

    wobes

    Joined:
    Mar 9, 2013
    Posts:
    669
    Could you provide an example of successful world initialization? I would much appreciate that.
     
  39. wobes

    wobes

    Joined:
    Mar 9, 2013
    Posts:
    669
    Adding just a single system simply doesn't work.

    Code (CSharp):
    1.         public List<Type> Initialize(List<Type> systems)
    2.         {
    3.             World serverWorld = new World(Bootstrap.ServerWorldName);
    4.  
    5.             // create presentation system and simulation system
    6.             InitializationSystemGroup initializationSystemGroup = serverWorld.GetOrCreateSystem<InitializationSystemGroup>();
    7.             SimulationSystemGroup simulationSystemGroup = serverWorld.GetOrCreateSystem<SimulationSystemGroup>();
    8.             PresentationSystemGroup presentationSystemGroup = serverWorld.GetOrCreateSystem<PresentationSystemGroup>();
    9.  
    10.  
    11.             simulationSystemGroup.AddSystemToUpdateList(serverWorld.GetOrCreateSystem<TestSystem>());
    12.             simulationSystemGroup.SortSystemUpdateList();
    13.  
    14.             return null;
    15.         }
     
    unitexer likes this.
  40. Piefayth

    Piefayth

    Joined:
    Feb 7, 2017
    Posts:
    58
    I have not had success creating worlds inside my custom bootstrap's Initialize. Not recommended.

    Use DefaultWorld.Initialize elsewhere to create your world. This will automatically load it with the default systems, THEN your custom boostrap Initialize will be called with that world set to the active world and you can remove types you don't want.

    I did a little writeup on this here: https://piefayth.github.io/blog/#!/posts/ecs_render_multiworld - the first half of that post should be a usable example. There is a mistake there, though - I use the UpdateInGroup attribute to determine which systems to remove, but in that particular instance I could've just removed the presentation group from the list of types directly, rather than trying to locate and every system inside it. i.e. I should update that bit to

    Code (CSharp):
    1.  
    2. if (World.Active.Name == "Server World") {
    3.     for (int i = 0; i < types.Count; i++) {
    4.         if (types[i].Equals(typeof(PresentationSystemGroup))) {
    5.             types.RemoveAt(i);
    6.             i--;
    7.         }
    8.     }
    9. }
    10.  
     
    jdtec likes this.
  41. wobes

    wobes

    Joined:
    Mar 9, 2013
    Posts:
    669

    Code (CSharp):
    1.         public List<Type> Initialize(List<Type> systems)
    2.         {
    3.             var testWorld = new World("Test World");
    4.  
    5.             var simulationSystemGroup = World.Active.GetOrCreateSystem<SimulationSystemGroup>();
    6.  
    7.             simulationSystemGroup.AddSystemToUpdateList(testWorld.GetOrCreateSystem<TestSystem>());
    8.             simulationSystemGroup.SortSystemUpdateList();
    9.  
    10.             return new List<Type>();
    11.         }
    That one works. Thanks to @eizenhorn
     
    Sarkahn, drhodor and Piefayth like this.
  42. Sibz9000

    Sibz9000

    Joined:
    Feb 24, 2018
    Posts:
    80
    You can also call UpdatePlayerLoop() after you create your world. This will add all the default systems (Init/Sim/Pres SystemGroups and associated buffer systems). Also do that after you've added your custom systems and there should be no need for
    AddSystemToUpdateList 
    &
    SortSystemUpdateList
    (EDIT: you do still need to do this)
    NB: All 'default' systems are shared across worlds.

    Code (CSharp):
    1. ScriptBehaviourUpdateOrder.UpdatePlayerLoop(testWorld);
    Note, this is fixed behaviour in entities.30, was broken in entities.<29
     
    Last edited: Apr 20, 2019
  43. Sibz9000

    Sibz9000

    Joined:
    Feb 24, 2018
    Posts:
    80
    You shouldn't need to call
    DefaultWorldInitialization.Initialize
    unless you have disabled automatic world initialization, and should only need to call it once - you can then use the ICustomBootstrap.Initialize to init your custom worlds, return null to disable the default world.

    As per my post above, just call UpdatePlayerLoop after creating your world and added systems and it should work as expected now. No need to add Init/Sim/Pres system groups or Begin/End buffer systems.
     
  44. Piefayth

    Piefayth

    Joined:
    Feb 7, 2017
    Posts:
    58
    Yeah, some interesting stuff here. I only took a moment to look into it, but it seems like none of my custom systems get initialized if I don't use DefaultWorldInitialization. Calling UpdatePlayerLoop will create the default ones, but that's it. One of the reasons I started using DWI was to take advantage of not having to manually initialize every system / manually declare their update order; if there's a way to get UpdateBefore / UpdateAfter and automatic system creation working in multiple worlds without DWI, it's unclear to me and I'm quite interested in it. :)
     
  45. Sibz9000

    Sibz9000

    Joined:
    Feb 24, 2018
    Posts:
    80
    Yes as Piefayth mentions, you can filter by interhace on the system list passed in.

    This is untested but should world:
    -snip- Removed as it didn't work
     
    Last edited: Apr 20, 2019
  46. Sibz9000

    Sibz9000

    Joined:
    Feb 24, 2018
    Posts:
    80

    Alright I'll run a test in a new project separate to my CustomWorldBootstrap and get back to you.
     
  47. wobes

    wobes

    Joined:
    Mar 9, 2013
    Posts:
    669
    I can confirm that UpdatePlayerLoop does not add default buffer systems. Also removing AddSystemToUpdateList && SortSystemUpdateList results an empty world without any created systems.

    I got everything working flawlessly with the approach above.

     
    Last edited: Apr 20, 2019
  48. Sibz9000

    Sibz9000

    Joined:
    Feb 24, 2018
    Posts:
    80
    It does, it just doesn't show them in the entity debugger.
    upload_2019-4-20_12-47-40.png
    (Thats a hover over the MyWorld variable)
     
  49. wobes

    wobes

    Joined:
    Mar 9, 2013
    Posts:
    669
    Thank you. But I am not sure if I need any of those.
     
  50. Sibz9000

    Sibz9000

    Joined:
    Feb 24, 2018
    Posts:
    80
    Scratch that, they get removed and put into default world after you return the list of systems.