#Understanding the benefits of ECS better.

1 messages · Page 1 of 1 (latest)

nocturne wyvern
#

My “understanding” so far is that if you have multiple lets say enemies sharing the same behavior one will benefit from using ECS or dots as a whole.
But what about a single gameobject that is checking for its distance against 20, 30 or 100s of other GameObjects. Is there any benefit in using DOTS or ECS there?
Apologies if this does not make any sense I am fairly new to DOTS. Thanks.

winged silo
#

There is a big benefit in that you're not using random access to find the position of those other game objects but instead iterating over contiguous memory. Ideally no cache misses and many awkward trips to main memory!

nocturne wyvern
#

So does that technically mean its faster?

winged silo
#

As the graph shows, accesses caches (L1, L2, L3) is vastly vaster than accessing main memory (this requires kernel calls).
So yes, technically faster to go through cache lines than following pointers to arbitrary parts in memory.

nocturne wyvern
#

Thats great. Thank you so much @winged silo for taking the time

winged silo
#

I'm very new to DOD as a whole so I'm glad to help where I can.
New as in I'm currently taking a course about it and as such have not touched DOD/DOTS/ECS before 3½ months ago ish. It does help to have people from the DOTS team actually run the lectures though 🙂

nocturne wyvern
#

That’s awesome, where are you taking the course?

#

Would like to get started on DOTS myself

winged silo
#

IT University of Copenhagen, course is completely new. And frankly will be a lot better next fall since 1.0 will be out with proper documentation 😂

nocturne wyvern
#

Oh thought it might be an online course. Well thats great and wish you the best of luck in your course

#

Again thanks 😄

true yew
#

I wonder where in the graph access via ComponentDataFromEntity would be, as that's likely what you'd use in OPs use case of distance checking against a lot of entities from the POV of one enity.

winged silo
#

Ehhh, I don't remember right now but there was a method for basically getting the array of the components from memory.
Then you can loop over that. ComponentDataFromEntity is entity indexed so you can't simply pointer arithmetic across it necessarily.
It should definitely be simple enough to manage though. Memory's just failing me on the functions right now

true yew
#

I think you can only get the array when on the main thread, unless there's something I'm not aware of.

lean dragon
#

Every individual lookup of an entity through a ComponentLookup (formerly known as ComponentDataFromEntity), you're paying the cost of a random lookup, so leaning heavily on lookups is best avoided when you can. Certain problems by their nature may require such random lookups because sometimes your entities just have 'random' relationships, e.g. 'this specific key opens that specific door'.

#

For collision/proximity checks (or other kinds of comparisons) between all X entities and all Y entities, you can do something like this:

  1. use EntityQuery.ToComponentDataArray<T> to get a copy of all T component values for the entities matching the X query
  2. loop over all Y's, and for each Y, loop over the array of X entity T components

This of course is an n^2 loop, so it's also something to try avoiding when you can, especially for large sets of X and Y.

For medium and large scale collision/proximity checks, you'll want to do some kind of "spatial partitioning". This is demonstrated in a new sample in the (coming very soon) updated ECS samples (https://github.com/Unity-Technologies/EntityComponentSystemSamples).

winged silo
#

Thanks for filling in, Brian!
I think ToComponentDataArray was what I was thinking of. Haven't used it myself so I wasn't aware of it making copies.

true yew
# lean dragon For collision/proximity checks (or other kinds of comparisons) between all X ent...

EntityQuery.ToComponentDataArray<T> is main thread only, right? And I assume it must complete dependencies to do so?

Doesn't that mean that access via ComponentLookup/CPFE might be preferable, as that can happen on other threads? Basically, it might be better to do slower work on another thread rather than faster work on the main thread.
Although, this still relies on EntityQuery.ToEntityArray to get the entities to do component lookups inside the job of...

lean dragon
#

Yes, jobs cannot perform queries, so you can only call it on the main thread, and this triggers completion of outstanding jobs with write access to the same component type. I'd have to check, but I'm pretty sure ToEntityArray doesn't require completing any jobs (jobs can't possibly modify entity id's, after all).

In some cases, then, the cost of the sync might outweigh the cost of the entity lookups, but I'd say that's generally atypical.

true yew
lean dragon
winged silo
lean dragon
lean dragon
winged silo
#

I was thinking of, say, comparing player position to positions of the different enemies. For range based aggro triggering perhaps. In such a case, it makes more sense to just loop over the enemies with the player position copied into the jobs I think

true yew
#

Yes, I was thinking that the ToEntityArray should wait for job completion, as the addition/removal of components in other jobs may impact the result of ToEntityArray. But then I realised that ToEntityArray does not have to wait for jobs, since the structural changes that could impact the result would only happen at sync points, not in jobs (jobs merely issue commands for structural changes to the command buffer systems). In short: structural changes don't happen in jobs, and therefore ToEntityArray doesn't need to wait for jobs 😅

steady walrus
#

also ToComponentDataListAsync exists

lean dragon
true yew
lean dragon
#

yes, the *Async variants can spare you from triggering a sync

winged silo
#

The best advice I have for that, Rupture, is "try, profile and compare".
That's the only way to know which is faster in your specific use case. As it always is 😅

lean dragon
#

Job system scheduling overhead has generally improved since 0.50 days, but the real answer is to always 'profile if it matters'