Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

What's the best way to inject world state data into jobs?

Discussion in 'Entity Component System' started by waxx, May 19, 2020.

  1. waxx

    waxx

    Joined:
    Apr 1, 2013
    Posts:
    48
    I'm working on a traffic system that has an infrastructure struct that contains native arrays with all the roads, nodes, connections etc.

    I would like to pass that "world state" to my jobs that operate on entities (cars). Suppose I have a JobComponentSystem that takes care of steering - should I inject that state in my OnUpdate method and pass it as a [ReadOnly] field to the job itself? Should I use a singleton entity instead that stores world state in a component (if so - how do you go about accessing that)? Is there any other way to handle this? What is the go-to workflow?

    EDIT:

    I've just realized that I can't pass an object like this with native arrays, because apparently I can't have structs with native arrays in them. No idea then how to structure my data.

    This is the layout:

    Code (CSharp):
    1.     public struct TrafficInfrastructure
    2.     {
    3.         public NativeArray<TrafficRoad> roads;
    4.         public NativeArray<TrafficNode> nodes;
    5.  
    6.         /// <summary>
    7.         /// Key - node id. Values - connections array.
    8.         /// </summary>
    9.         public NativeMultiHashMap<int, TrafficConnection> connections;
    10.     }
    11.  
    12.     public struct TrafficRoad
    13.     {
    14.         public int nodesCount;
    15.         public int startingNodeId; // This lets us easily access the nodes array to find the right nodes
    16.     }
    17.  
    18.     public struct TrafficNode
    19.     {
    20.         public float3 position;
    21.     }
    22.  
    23.     public struct TrafficConnection
    24.     {
    25.         public int destinationRoadId;
    26.         public int destinationNodeRelativeId; // Needs to be added to startingNodeId of the road to retrieve actual index
    27.     }
    I can't make this run because of native arrays... no idea how to store something like this.
     
    Last edited: May 19, 2020
  2. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    3,984
    This is false. You cannot have a NativeContainer inside another NativeContainer. NativeContainers inside structs are fine. I'm guessing you are trying to make a NativeArray of a struct containing a NativeArray, which falls into the NativeContainer inside another NativeContainer case.
     
  3. waxx

    waxx

    Joined:
    Apr 1, 2013
    Posts:
    48
    Yeah, that's right. I need to have a HashMap with different TrafficInfrastructures for different types of entities (cars, pedastrians). How should I structure the data then?
     
  4. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    3,984
    You should structure the data in a way that makes sense for the algorithms using it. I know nothing about those algorithms, requirements, nor frequency of change. Therefore, providing any suggestion would just be misleading.
     
  5. waxx

    waxx

    Joined:
    Apr 1, 2013
    Posts:
    48
    Well, my use case is quite simple. I have a traffic module which has a MoveSystem that iterates over entities like cars and pedestrians. The MoveSystem queries for entities that have a component which stores information such as the infrastructure id, road id, node id, current velocity. It then needs to update those entities, guiding them from one node to another based on the collection of TrafficInfrastructure (that has all the const map layout data).

    So I need to use my infrastructure id to then access the correct TrafficInfrastructure struct. The issue is (as you've pointed out) that I can't just have a native array (or a hash map) of those structs that I'd just pass as a parameter to my job in the MoveSystem. Doesn't matter if they're initialized outside the ECS or within in form of a singleton entity. I tried just throwing in a regular Dictionary into the mix, but Burst fails to compile it.

    I'm truly at a loss on how to implement this.
     
  6. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    3,984
    Some options:
    • Blobs
    • Dynamic Buffers
    • Storing int2 of start index and range for another NativeArray with all the data
    • Unsafe versions of data structures (use at your own risk)