On Collision Performance (Tracking)

Get help using Construct 2

Post » Thu May 09, 2013 3:32 am


Could you please explain to me how the "On Collision Event" works internally?

For example, hypothetically, let's say that I have Event Sheet 1:
Obj1 On Collision Obj2 : Do some actions

Event Sheet 2:
Obj2 On Collision Obj1 : Do some actions

If I assume that the events in both sheets are run as a single concatenated logic loop, would it be correct to assume that the collision detection stores a dictionary of prior checked collisions for objects? In this manner, Event Sheet 2's collision check cost would be minimal.

The reason that I ask is because I have two ways of handling collision detection at this point.

My original way was more modular, all objects belong to EntityFamily which has a local var called CollidedFn, which is a link to a function. All collision detection was centralized in a single CollisionEventSheet which would do something along the lines of:

On EntityFamily Collided with EntityFamily : Call EntityFamily.CollidedFn which would hand off the collision to the object's collision routine.

However, each object (which is represented in my project by a single event sheet) could also have an:
On Object CollidedWith EntityFamily : Do something (note that this is Object-specific)

However, if we're not tracking existing checked collisions in a single "loop cycle", having this On Collision statement repeatedly could get very computationally expensive.

I'm just trying to look for best practices here.

-- Cacotigon

P.S. I might be thinking about this the wrong way, are "On Events" different from regular events in the game loop? Are they maybe like delegate triggers?

Posts: 232
Reputation: 6,089

Post » Thu May 09, 2013 10:02 am


i dont know the answer to your question, but i did see Ashley reply to another performance related question recently and he pointed to this.

Posts: 1,096
Reputation: 10,988

Post » Thu May 09, 2013 1:09 pm

Internally, 'On collision' is not a real trigger even though it appears like one in the event sheet - it works like 'Is overlapping' with 'Trigger once' after it. This is for performance reasons (it would be difficult to avoid unnecessary collision checks if it was a real trigger).

Generally the performance of overlap tests is negligable unless you have hundreds of objects or more (see @spongehammer's link). However it's good practice to only have one overlap or collision test, and do everything you need to in subevents under that. If you have two 'On collision' or 'Is overlapping' events, it will re-check the overlap both times.

It could actually degrade performance to cache results, because if an object moves it has to remove any cached collision results. This means every time an object moves it has to do a little bit of work. Most games have a very large number of moving objects, which multiplies a little bit of work in to a lot of work. So I'm not sure that would actually make it faster.
Scirra Founder
Posts: 22,822
Reputation: 176,618

Post » Thu May 09, 2013 2:33 pm


EDIT: I just re-read your post in which you kind of address this potential solution. :p Sounds like as you've said, it might actually hurt performance.

Thanks for your reply.

What if you invalidated all cached Collision results for a given entity after any command which results in a change of position/angle/scale using some kind of HasChanged boolean?

So maybe you have a central collision Cache which is an internal dictionary, it is only added to when two elements collide. The key represents the unique instance of the object, and the value is a enumerable list of elements that it has collided with on this loop cycle.

CollisionMap[Obj1] = { Obj2 }; // set of objects Obj1 has collided with
CollisionMap[Obj2] = { Obj1 }; // set of objects Obj2 has collided with

So in the game loop:

Clear Collision Dictionary at beginning
Set all objects HasChanged = false

On Obj1 Collision Obj2 routine: (doesn't actually do any bound checking yet)
Foreach(Obj1 in Layout)
-- Foreach(Obj2 in Layout)
-- -- If Obj1.HasModified = false && CollisionMap[Obj1].Value.Contains(Obj2) { TriggerCollision(); }
-- -- Else { Run Normal collision bounding checks -- save results into CollisionMap }

Would this help to optimize collision performance at all?
cacotigon2013-05-09 14:35:32
Posts: 232
Reputation: 6,089

Return to How do I....?

Who is online

Users browsing this forum: 99Instances2Go, makkancs, makotto and 21 guests