Picture an octopus entity connected to 8 arm entities by physics joints. If two octopus arms are close enough together, they can link together to hold a gun and pull the trigger. There can be many octopuses in the world. I’m designing a way to detect, in a system, whether or not two arms are close enough together for this condition to be true. For purposes of this discussion, assume octopuses may varying number of limbs, but usually around 8.
I have 3 candidate ideas -
use the common entityID (the octopus ID) as a shared component value. Then iterate through chunks and check proximity only against other arms in the same chunk, since the arms with the same octopus id would be in the same chunk (right?) Possible cons: lots of octpodes mean pretty small chunks. and in theory isnt it possible that an octopus’s arms could be split onto multiple chunks?
Use the octopus ID as a shared component value, then when the system updates, run queries with .SetFilter to select the arms for each octupus and load them into arrays. then I guess do some processing against those arrays? I dont really know what iteration mechanisms I have at my disposal in this case.
give the octopus entity a buffer of children. then during the octopus system, walk through each of those children using the entity manager to get their translation components. if any are found to be close enough together, use the entity manager to walk to those children and somehow indicate that this condition is true so that during the arm system that fact can be used. This seems the least performant/ most random access… although perhaps has the least unknowns
I suppose a 4th idea might involve raycasts during the ForEach(Arm) system, but that seems too expensive.
Not sure why you would do 3 using EntityManager instead of doing it in a burst job, which I suspect this will actually be the fastest solution. It’s really not that costly to compare distances of known objects. If you don’t want to jump in memory, keep a cached position in the buffer as well.
Something I’m trying to optimize atm in our project as it approaches the final stages before launch (hopefully announced soon so I can actually talk about it more), is that over time querying entities can actually start to become quite slow as archetype counts increase (especially on platforms that are say, 7 years old.)
Performance difference of between 40 seconds (left) vs 24 min (right) into game of just the system querying if it should run.
About 50% worse.
Disclaimer: I’m a well known SCD hater around here and don’t think anyone should ever use it except to optimize very specific circumstances. This takes a lot of experience which anyone asking for help on the forums likely does not have so I blanket advise people against using it.
Thats some interesting data. Congrats on approaching launch!
I’m not entirely sure what you mean by doing it in a burst job. I thought burst optimization was something that got abstracted into chunk iteration and entities.foreach .scheduleparallel processing jobs
Well Burst is a compiler that translates IL bytecode to highly optimized native code, although it is made specifically for C# Jobs (it’s also possible to use Burst-compiled code outside jobs). You can use Burst-compiled jobs for processing native collections such as NativeArray outside ECS.
For the original question, you have to consider some things before going into SCD route. SCD chunk processing is probably the fastest solution here, but remember that segmenting your entities too much will make other queries over your octopus arm entities that doesn’t need about your octopus-ID SCD slower. From my experience, SCD works great only if you REALLY need to segment your entities based on this SCD value and if it is the only (or one of the few) values that segments your entities and you rarely need to query your entities any other way.
I’d for the for 3rd route but as tertle said cache the child positions. But really I think you’d do more than fine with a naive approach like iterating over all arms and checking if two arms are from the same octopus and distance checking is really cheap, especially with parallel job and burst.
might do naive checking then. Never know when octopuses are going to want to start working together, after all. Then perhaps in the future if necessary I can try doing a “spatial hashmap” - which as I understand it is something done in the boids ecs sample project for collision detection