Collision: Colliding with multiple nodes at once


I want my characters to collide with the rooms they’re in. I want polygon-exact collision (the rooms have complex shapes). For performance reasons, I split my map into many collision “chunks” and only collide with those 27 chunks surrounding the character.
Now I’m trying to cast a ray at these closest collision chunks. How do I traverse them all at once?
They all share a common ancestor node which I could call traverse on, but so do all the other collision chunks which are further away (and I don’t wan the ray to collide with them). I could re-parent the chunks in question to a new temporary node, but this sounds expensive.

My current workaround is to call traverse on each of them individually, but then each of them (potentially) fills a separate CollisionHandlerQueue which I then have to sort through manually to find the closest hit. This works but is really ugly.
I believe I can’t turn the problem around (filling the Traverser with the Chunks and then traversing the node with the CollisionRay attached to it) because a CollisionRay can only be used as a “from” object.

Am I missing a cleaner method for colliding with multiple objects at once?

Just to check: Have you tried just calling “traverse” on the common ancestor of all of your chunks, and if so, have you tried (as you suggest) reparenting the 27 nearest chunks to a temporary node?

After all, I would expect that the collision system has means of culling which objects it examines–perhaps that alone is enough. And if not, 27 chunks isn’t so many–perhaps reparenting them will be fast enough. (It may sound expensive, but I daresay that sometimes such impressions are proven wrong.)

1 Like

You might be able to speed up the reparenting by using a NodePathCollection. E.g. parent_nodepath.children returns such an object, but you can also create them manually and append NodePaths as you like.

It has methods similar to those of single NodePaths as well as list-like methods.

So you could do something like this:

# create an empty collection,...
closest_chunks = NodePathCollection()
#...fill it with the "chunk" nodes...
for chunk in chunks:
#...and reparent the entire collection at once
# later, the collection can be reparented again to the original parent

But instead of reparenting, perhaps more useful to you is the ability to set a collision mask on a NodePathCollection. So you could first split off the collection of closest chunks from the complete collection of chunks and set a collision mask only on the former:

# create a collection of all "chunk" nodes
all_chunks = parent_node.children
# create an empty collection,...
closest_chunks = NodePathCollection()
#...fill it with the closest nodes...
for chunk in chunks:
#...and remove this collection from `all_chunks`
# make it possible to collide with the closest chunks

Afterwards you can add the collections together again and set a “no-collision” mask on them:

# merge both collections into one again
# turn off collision for all chunks

Note that it’s been a while since I’ve worked with the collision system, so I may well be mistaken about the use of collision masks!



thank you both for the quick replies - I haven’t gotten around to benchmarking any of these. I will start with the simple approach of just traversing the common ancestor for now and if I notice any slowdowns as I add more characters I’ll revisit the other ideas. I guess it was naive of me to assume that traversing over all the chunks gets too slow.

I’ll also look at NodePathCollections, they look really interesting. I wasn’t aware of these - thanks!
I think collision masks are what I was originally searching for with this question, thanks for that pointer as well! I guess I now have quite a few things to try out… :slight_smile: