Search Unity

In Game Metrics

Discussion in 'Entity Component System' started by tbg10101_, Dec 4, 2020.

  1. tbg10101_

    tbg10101_

    Joined:
    Mar 13, 2011
    Posts:
    192
    I have game where different object accumulate heat. This heat comes form various sources. (a positive amount for sunlight and excess energy / a negative amount for radiators) I want to display the amount and the sources in a UI.

    There could be hundreds or thousands of these objects.

    One option I have considered is to have each system that adds heat output a list. However this limits me to Schedule calls and a lot of these are just adding a number to another so I'd like to be able to keep my ScheduleParallel calls. I also don't like the idea of having to manage/merge a bunch of lists.

    Another option is to create a new component which has a field for each source of heat and populate the fields when sources add heat. Then the UI would just read the component data for each object when it needs it. This seems wasteful, though, since no other system will read the data so it seems like extra weight that just makes my chunks smaller, especially if I add more and more sources of heat to the game.

    Questions for the ECS veterans here: Which one of these seems best considering performance and code smell? Am I missing a better solution?
     
  2. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    4,271
    I'm assuming only a selected object displays its sources? And the sources can be recalculated every frame? If so, you could check if the selected object has a HeatSources component. If it does not have the component, add it via ECB. And if it does, display it. This will have a one frame latency but will reduce the calculation of heat sources to a single entity.
     
  3. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,780
    Each heat source is the same hindind of heat right?
    I assume, you want to accumulate total of heat from related heat sources, affecting given entities.

    So, you could make system in such way. They are heat source driven, or heat receiver driven.

    If re eiver entitiy driven, you would have single system that is responsible for adding a heat.
    What it would do, it would check receiver entities, for its assigned heat sources. You could store for example heat sources entities in a DynamicBuffer. Then add remove heat sources as needed, in relevant system, corresponding to specific heat source.

    Then you simply run for each system, of receiver entities, which has at least one heat source active. You may want to use IsHeatsourceActiveTag component, for that purpose.

    Each source entity when in range of entity heat receiver, can use for example system, which will use ecb, to request add relevant heat source to entity receiver dynamic buffer.

    You would be probably not need to call this system every frame for same entity.

    But probably you could limit your logic to two systems. Send request to add heat source. And other, which process all receiver heat source entities and their sources every frame if needed.


    Other option is source driven.
    Probably suitable, when having many different sources in thousands.

    What I would try to consider, is to use MultipleHashmap. Not sure if for best approach however.
    Each source checks all their receivers that may be in range. You could do that per frame.
    You add affected entities as key and heat strength as value to hashmap.

    When all heat sources entities are done, you grab unique keys from multiHashMap, which correspond to receiver entities and process parallel job for each key, iterating and summating values of heat per key, for given receiver entity.


    You could also use ecb to grab heat from sources, by instantiating entities with heat values, as events, or send from sources, but then, I think you would need to accumulate values per receiver, on single threaded job.
     
  4. tbg10101_

    tbg10101_

    Joined:
    Mar 13, 2011
    Posts:
    192
    That is one use-case. The other is to see all the objects in a table so you can get an overview of all the objects. Another is a visualization view, which colors all the objects based on how much heat they are generating.



    I'm really trying to track the source of heat that each object produces, not the heat that they spread to each other. Each object generates heat itself. So maybe it is more accurate to say that I'm trying to track heat source types and the amount of each type that each object generates.
     
  5. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    4,271
    At this point, I would consider making a table structure per thread using m_ThreadIndex (if memory is concerning, you can make it sparse) and have your parallel jobs write to it and right before presenting, you have a job that merges them.
     
  6. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,780
    Providing I understood your goal correctly, in such case, if each entity can hold multiple type of heat sources and of different values / strength, I would use Dynamic Buffer. Buffer component would contain relevant values and / or type of heat sources.
    You can easily use an enumerator, as heat type.
     
    tbg10101_ likes this.