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. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice
  4. Dismiss Notice

Question ECS Escaping from Structural Changes - Filtering Entities

Discussion in 'Entity Component System' started by nomadshiba, Mar 23, 2022.

  1. nomadshiba

    nomadshiba

    Joined:
    Jun 22, 2015
    Posts:
    27
    In ECS, if you wanna do filtering based on some state, using tags is the way to go.
    This can make the filtering of the entities really fast but it also has downsides, like Structural Changes.

    When we talk about Structural Changes, people say, "make structural changes only on user input" or stuff like that. So it doesn't happen every frame.

    But let's say you have an alive world or something like that, like you need to do Structural Change even if the player is not giving inputs. Then as you have more and more entities that has to do these Structural Changes time and time in order to work and filtered by the Systems, you start to have more and more Structural Changes happening on a every frame.

    One approach would be using flags with boolean or enums instead of tags. But the problem with this is, if you have many different flags then your systems mostly gonna have to skip many entities that it has to do nothing with it.

    What other approaches do have to this problem, without Structural Changes while also keeping ScheduleParallel?
    Something like using flags but without it's downsides(like having no filter at all).
    We can sacrifice CPU caching.
    I was thinking about what can be done with the new Entities.WithFilter(NativeArray<Entitiy>).
     
  2. JesOb

    JesOb

    Joined:
    Sep 3, 2012
    Posts:
    1,081
    read about per component enable flag that will be in ECS 1.0
    It is way to go but only in 1.0
     
  3. nomadshiba

    nomadshiba

    Joined:
    Jun 22, 2015
    Posts:
    27
    ok i did some tests
    so turns out random memory access is slower than having many structural changes every frame
    so using tags is the way to go
     
  4. nomadshiba

    nomadshiba

    Joined:
    Jun 22, 2015
    Posts:
    27
  5. Enzi

    Enzi

    Joined:
    Jan 28, 2013
    Posts:
    910
    Interested in your test case.
    Random access far out-performs structural changes.
    Either 0.50 has drastically improved structural changes or something else is going on in your test. Do you have a dynamic buffer in the query? Could explain it.
    The way to go until 1.0 hit is having bool fields and checking in your systems. This was the suggestion from Joachim when this was a hot topic.
     
  6. nomadshiba

    nomadshiba

    Joined:
    Jun 22, 2015
    Posts:
    27
    You are right.
    But.
    Also, I still need to remove the Entity from the array. I first thought i can use RemoveAtSwapBack
    But can't because there are multiple stuff to remove every frame and RemoveAtSwapBack mixes the list.
    So I have to use RemoveAt which is not ideal.

    So, iterating through a NativeList is not slow by itself but when we add other stuff to make it functional its slower than the structural changes method.

    NativeList: ~7-8ms
    Structural Changes: ~4-5ms
    Using boolean: < 1ms
     
  7. Enzi

    Enzi

    Joined:
    Jan 28, 2013
    Posts:
    910
    Do you remove from the NativeList in a burst method or bursted job? Utilizing NativeContainers in normal main thread is very slow and it's not intuitive to know about this performance characteristic.
     
  8. vectorized-runner

    vectorized-runner

    Joined:
    Jan 22, 2018
    Posts:
    383
    I think it depends on how frequent the state changes, and if the state changes are permanent.

    For example including a Dead tag could be more performant since Dead entities isn't likely to come back, and stay dead, so instead using a flag we could sort by it and it would be faster.

    But something like AI state, which could be changed every frame, would cause a lot of structural changes and performance could be worse, so you check it each frame

    There is no simple solution, either sort by type it or check the type