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

What about when there is only one entity...

Discussion in 'Entity Component System' started by Arowx, Jul 9, 2019.

  1. Arowx

    Arowx

    Joined:
    Nov 12, 2009
    Posts:
    8,194
    DOTS uses ForEach to find entities of a given type, the thing is sometime in a game there is just one thing, e.g the player, score, UI, screen or a fixed number of things.

    So should there not be a simpler 'Singleton' System that just works on one entity and holds a reference to that thing or a finite number of fixed things?

    It just seems like sometimes DOTS has us jumping through loops (pun intended) to work with things we used to be able to hold references to and access directly.
     
  2. BanJaxe

    BanJaxe

    Joined:
    Nov 20, 2017
    Posts:
    47
    ComponentSystem has GetSingleton/SetSingleton/HasSingleton. Under the hood they just check that there's exactly one in existance, they don't enforce it.

    Also RequireSingletonForUpdate if you only want the system to run when the singleton exists.
     
  3. Deleted User

    Deleted User

    Guest

    I agree. It feels awkward and wrong to use a ForEach when you know it's gonna be one entity. I think it's better to add new API for single entities.
     
  4. 8bitgoose

    8bitgoose

    Joined:
    Dec 28, 2014
    Posts:
    448
    I also feel there are some crazy hoops you have to jump through to get data in the right order. Most of the work I do is data marshaling so it can get processed quick.

    Also a single entity will take up a whole chunk. So that adds memory overhead. I can't think of a good solution to make singletons easier.
     
  5. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    4,222
    I have an evolving framework built on top of ECS and one of its features is what I believe to be a more intuitive singleton system.

    Instead of having "singleton components", I have a "SingletonEntity" which is a property of my base system classes (which are subclasses of Unity's ComponentSystem and JobComponentSystem classes). The SingletonEntity holds the true entity and a reference to the entity manager and has entity manager shorthand methods.

    To get the Entity shared between systems there's two different approaches.

    The sane approach: Create a dedicated system and have all the other systems use GetOrCreateSystem to get the singleton entity in OnCreate.

    The not-so-sane approach: Subclass World and store the singleton entity there. Then use an ICustomBootstrap to replace the default world with the subclassed world. I do this. It probably isn't necessary, even with all the other custom stuff I do. I just felt like that's where the data should belong.

    I also have a system which merges all entities tagged with a SingletonTag component into the singleton entity and then deletes the source entities. The code for that right now is ugly. It is on my todo list to figure out how to inject this merging process into the world merging mechanism so that I don't have to run this every frame.
    • Pros
      • Debugging singletons is way easier. It shows up right at the top of the EntityDebugger with all the information.
      • Works really well with GameObjectConversion authoring workflow.
      • Has smaller memory footprint.
      • Works with any data type that can be attached to entities, including custom types (if you are crazy like me and figure out how to do that).
      • Allows other instances of the components to exist on other entities which can be useful in a lot of cases.
    • Cons
      • Does not integrate with update-on-query mechanism. (I don't use that "feature".)
      • Technically more characters to type.
      • Technically more expensive to add and remove components since all the data needs to be copied to a new chunk each time.
    Recently I have been doing weekend game jams as a more fun way to build and test my framework that my larger projects depend on. The SingletonEntity is by far and away the most useful piece of tech I have built for these jams.

    Also I should mention that using this singleton for the player is a terrible idea and I use Entities.Foreach for the singular player in all of my games. The singleton is for more important game management information such as scene, scene state, level spawn rates, important prefabs, ect.
     
  6. Arowx

    Arowx

    Joined:
    Nov 12, 2009
    Posts:
    8,194
    Why if there is only one player, it's like making an array for one item and a loop to go over the items?

    Surely the overhead of using a system to check if one item exists and then get it is greater than just having a system that holds a reference to an entity?
     
  7. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    4,222
    Making a the player a singleton is terrible and you should never do it!

    JK :p

    It is one of those mistakes that is difficult to understand until you get burned by it.

    Many of the issues transfer over from why Mono-land player singletons are bad. I'll let you google those discussions yourself, but to summarize, such singletons generally create unnecessary coupling between systems that would otherwise be non-discriminatory towards the player and the player itself which is one of the most evolving parts of your game during development.

    But in ECS, there's two easier-to-understand reasons. The first is that by not making it a singleton, I naturally account for the 0 players case. That lets me destroy the player and re-instantiate it from the prefab without disastrous side-affects.

    The other reason is that often-times the player is composed of multiple entities. In one of the recent game jams I did, I had a player spaceship and a player pilot. I wanted to be able to destroy the spaceship without destroying the pilot. When the pilot detected the space-ship was gone, it would enter a respawn timer state, play an animation, and then instantiate a new spaceship assuming there was an available spaceship left for the player's team.

    So while the overhead is greater if I always know there is one, the overhead is pretty much equal if there's a chance there is 0, and writing code this way makes the code more modular for projects that can't make as aggressive of assumptions. Plus if I ever want to add 2 player co-op, I don't need a total paradigm shift.

    Also keeping the player entity separate from the game manager entity (what my singleton entity usually represents) makes stuff a lot easier to debug.
     
    jdtec and RBogdy like this.
  8. 8bitgoose

    8bitgoose

    Joined:
    Dec 28, 2014
    Posts:
    448
    This is off the top of my head but if you have a singleton why don't you just make it a system? Systems just loop through all the entities but if you have a singleton you just store the player position on the system and fetch it through a static Instance class. I wouldn't do it this way because I feel like it would confuse future programmers but at least you aren't wasting chunks and memory. It would make it easier than having to set up queries to find a single entity all the time.
     
  9. Deleted User

    Deleted User

    Guest

    AFAIK having static fields is against the ECS paradigm.
    It would be useful if one of unity staff said a word about this subject.
     
  10. They did. Multiple times. Although it's possible that it's slightly harder to find in the sea of threads.
     
  11. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    4,222
    Statics are one of those things that are kinda alright right now but are going to become one of those big no-nos in Unity like foreach, string concatenation, and instantiate/destroy patterns used to be. This is because in 2019.3 domain reload on play will be optional but statics won't be reset.

    Anyone who has had the joy and pleasure of cleaning up exceptions from statics on scene changes can probably guess what storm awaits.
     
    8bitgoose and jdtec like this.