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

Simple system to DOTS.

Discussion in 'Entity Component System' started by Greenwar, Nov 16, 2020.

  1. Greenwar

    Greenwar

    Joined:
    Oct 11, 2014
    Posts:
    54
    So while working with ECS on my spare time I'm still having a really hard time readjusting my way of going about solving things in non-OOP-land. I decided on creating/converting a simple constraints system into DOTS as an exercise and I got stuck right away.

    I don't know if I'm just laughably stupid or just going about things wrong. Probably both
    Either way, shifting my mindset as well as wrestling with an ever changing API got me all sorts of confused.

    Anyway, here's a super simple constraints system in MB.

    Code (CSharp):
    1.         for (int i = 0; i < balls.Count; i++)
    2.         {
    3.             for (int j = 0; j < balls.Count; j++)
    4.             {
    5.                 var curDisplacement = (Vector2)(balls[j].transform.position - balls[i].transform.position);
    6.                 if (!(curDisplacement.magnitude < radius)) continue;
    7.                 var offset = (Vector3)(curDisplacement - (Vector3.one * curDisplacement.normalized));
    8.                  
    9.                 balls[i].transform.position += offset /2;
    10.                 balls[j].transform.position -= offset /2;
    11.             }
    12.  
    13.         }
    Which yields:

    Slow, inefficient, cash-miss city, rudimentary, etc, etc - but it gets the point across.

    DOTS
    Now, I was hoping to port the above into ECS/DOTS. Preferably with as much parallelization and performance as possible, minus spatial partitioning techniques, for now.

    My first issue is that the above code requires random access, which is a big no-no afaik. Even so, if you were willing to take cash-misses I wouldn't be too sure how to properly inner-loop all entities in a Entities.Foreach.
    Is GetComponentDataFromEntity<Translation> the way to go? RW Parallelization goes out the window at that point, no?

    Perhaps some sort of double buffering is common practice, I don't know. I'm really at a loss.
    Linearly processing of each entity is trivial, but entity interactions are a mystery to me.
     
    Last edited: Nov 16, 2020
  2. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,754
  3. Joachim_Ante

    Joachim_Ante

    Unity Technologies

    Joined:
    Mar 16, 2005
    Posts:
    5,203
    The simplest approach is to copy the translation values to a tightly packed array.
    Using var positionArray = EntityQuery.ToComponentDataArray<Translation>().

    Then use Entities.Foreach where you iterate each ball and you write to the translation values based on the constraint.
    Then you simply have a for loop over the positionArray to solve the constraints.

    This way you can write perfectly parallel code.

    In practice a spatial index is likely more important than any other optimisation if your ball count will grow beyond something like 250.
     
  4. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    4,223
    Take baby steps. The biggest optimization is not cache-efficiency, parallelization, or simd. The biggest optimization is Burst (yes, even for stupid scalar do things backwards code). So let's start with a solution that ports your existing logic to Entities.ForEach.

    You'll probably have something like this:
    Code (CSharp):
    1. var entityArray = m_query.ToEntityArray(Allocator.TempJob);
    2. Entities.WithAll<BallTag, Translation>().WithStoreEntityQueryInField(ref m_query).ForEach((Entity entity) => {/* ... */}).Run();
    Inside, you won't have the "i" loop, just the "j" loop, and you use GetComponent and SetComponent to modify the translations.

    This isn't as easy to write as you make it out to be because @Greenwar is writing to both entities at constraint resolution, which can't be done safely in parallel using a brute-force technique.

    Parallel spatial pair processing is so common of a problem that I spent months designing a general-purpose solution for it. I've lost count how many times I have seen this type of problem come up in these forums.
     
    florianhanke likes this.