Search Unity

Question Reusing code between systems

Discussion in 'Entity Component System' started by Mogthew, Sep 26, 2020.

  1. Mogthew

    Mogthew

    Joined:
    Jan 30, 2013
    Posts:
    18
    I'm trying to figure out the best way to to handle a tree-like command structure. Making this burstable is important because it's a large bottleneck.

    Lets say you have something like this


    -Entity1-
    ConstructCommand
    + MoveCommand
    + PickupResources
    + MoveCommand
    + ActuallyPlaceTheStructureCommand

    -Entity 2-
    AttackCommand
    + MoveCommand
    + AttackObjectCommand


    Only one command on an entity will actually be executing at a time. A command may be comprised of many other commands. A command initializes, does work until a condition is met, and then is complete. Effectively, this is a tree of code.

    I've considered a few approaches but they all seem to be poor

    A public Job per system, and a system per command. Every system loops over the relevant entities and creates the appropriate job based on the current command state
    Could end up creating 20k jobs per frame, not really feasible.

    Create the full tree of commands when you create the top level command, and attach it to the entity
    Because of the amount of entities and the amount of permutations of command component data, this will lead to incredible fragmentation of the chunks. It's also very difficult to figure out how to transition between the states properly.

    A data object with the superset of all the fields every command has, stored in a NativeArray and iterated over by a single system with a giant switch statement.
    This is gross, but is what I'm currently leaning towards. It seems to be the only way to actually get any reuse of the system code. The component data will have loads of wasted space in it though, as a command may only use a couple of fields.

    Does anyone have any good ideas for how to implement this?
     
  2. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    4,271
    Having each command be an entity might be what you are looking for. One component could specify the command type as an enum letting you switch on it for faster archetype analysis. Other components could specify the data specific to the commands. In the case of a command containing multiple other commands, that becomes a dynamic buffer of command entities.

    StructLayout.Explicit can cut the memory cost down quite a bit. Just make sure that if you are serializing these in subscenes that any Entity or BlobAssetReference does not alias with any other variables.
     
    KAV2008 likes this.
  3. Mogthew

    Mogthew

    Joined:
    Jan 30, 2013
    Posts:
    18
    Interesting. I considered the entity per command but dismissed it primarily because I wanted to attach the data object to the entity the commands would be running against for performance reasons. If you don't do that it means each command will be reaching into arbitrary chunks to get data about the related entity. I should probably profile this before worrying about the performance though.

    I'll look into the StructLayout.Explicit and see if I can use it appropriately.

    Thanks for the suggestions :)