Cant get reliable 2d collisions?
by Daniel MacDonald · in Torque Developer Network · 05/09/2008 (1:44 pm) · 9 replies
Hi,
I'm trying out TGB to prototype a game, and I'd really like to be able to use it. However, the 2d collision system is not working as expected. I have a number of overlapping static objects that are all set to send and receive collisions.
I expect that as long as they continue to overlap (I've disabled physics), I will receive collisions on every object for each of its neighbors every frame, indefinitely. However, this does not seem to be happening. I will collide once or twice, but then I receive no further collisions. The objects are still clearly receiving _some_ collisions (onCollision is being called), just not from certain objects anymore.
I cant find anything in the documentation that would explain it, except possibly for setCollisionMaxIterations. I set this to 1000000 (>> than possible number of object pairs in my scene), and I still get nowhere... I did not touch any masks, layers, or groups. Collision mode is CIRCLE, the collision circles are all clearly overlapping, as are the object bounding boxes.
Whats going on here? How do I get reliable collisions?
Daniel
I'm trying out TGB to prototype a game, and I'd really like to be able to use it. However, the 2d collision system is not working as expected. I have a number of overlapping static objects that are all set to send and receive collisions.
I expect that as long as they continue to overlap (I've disabled physics), I will receive collisions on every object for each of its neighbors every frame, indefinitely. However, this does not seem to be happening. I will collide once or twice, but then I receive no further collisions. The objects are still clearly receiving _some_ collisions (onCollision is being called), just not from certain objects anymore.
I cant find anything in the documentation that would explain it, except possibly for setCollisionMaxIterations. I set this to 1000000 (>> than possible number of object pairs in my scene), and I still get nowhere... I did not touch any masks, layers, or groups. Collision mode is CIRCLE, the collision circles are all clearly overlapping, as are the object bounding boxes.
Whats going on here? How do I get reliable collisions?
Daniel
#2
Also, this forum area is for the Torque Developer Network wiki, used to post bugs/issues with the wiki itself. For TGB questions, you should probably slide over to the Torque Game Builder forums :)
05/10/2008 (9:41 am)
Glen is correct--forcing overlap and relying on onCollision calls every tick is going to really hurt your performance. You probably want to look at using onUpdate(), since it already provides a callback every tick for you to use.Also, this forum area is for the Torque Developer Network wiki, used to post bugs/issues with the wiki itself. For TGB questions, you should probably slide over to the Torque Game Builder forums :)
#3
Just to be clear though, you won't get it every frame as collisions happen every tick which is currently 1000ms/32ms = 31.25hz. You won't see a collision each frame, just every tick as each frame is simply interpolating positions but nevertheless you should see a continuum of collisions as you suggested.
Any chance you can fire me your project to "m e l v . m a y [ a t ] g m a i l . c o m"?
Melv.
05/11/2008 (11:05 am)
That's very odd but I'd like to mention that you should get "onCollision" each and every tick for every object that is colliding, overlaped or forward-time ... indefinately if you've stopped TGB solving the collisions and you're not doing anything to solve them yourself ... as you suggest.Just to be clear though, you won't get it every frame as collisions happen every tick which is currently 1000ms/32ms = 31.25hz. You won't see a collision each frame, just every tick as each frame is simply interpolating positions but nevertheless you should see a continuum of collisions as you suggested.
Any chance you can fire me your project to "m e l v . m a y [ a t ] g m a i l . c o m"?
Melv.
#4
To clarify: I want collision events every *tick*, and I want to be notified for each overlapping pair of objects, exactly as Melv stated. I dont care about performance, there arent that many objects involved.
When I have access to my computer again in a few days I will send you an example. Frankly though, I thought TGB was a really promising tool but between this issue and the irritation of torquescript I'm not too sure I want to purchase.
05/11/2008 (10:46 pm)
Thanks guys. Sorry about not getting the right forum. This was the only forum I found on my initial hunt. The actual TGB forum doesnt even appear to be linked from the forum main page, which I never even found on my own :) To clarify: I want collision events every *tick*, and I want to be notified for each overlapping pair of objects, exactly as Melv stated. I dont care about performance, there arent that many objects involved.
When I have access to my computer again in a few days I will send you an example. Frankly though, I thought TGB was a really promising tool but between this issue and the irritation of torquescript I'm not too sure I want to purchase.
#5
For example, if the objects aren't moving, you don't actually need a collision callback every tick--instead, on the actual overlap condition event (first time), but the object collided with into a SimSet, and then iterate over the set whenever you like (an onUpdate callback for example).
This is more in line with how the engine is designed to operate, and would probably save you quite a bit of hassle in the long run.
05/12/2008 (12:02 am)
Without a bit of information regarding what your real goal is, it's hard to tell, but I'm almost certain there is a much better way of handling your goal.For example, if the objects aren't moving, you don't actually need a collision callback every tick--instead, on the actual overlap condition event (first time), but the object collided with into a SimSet, and then iterate over the set whenever you like (an onUpdate callback for example).
This is more in line with how the engine is designed to operate, and would probably save you quite a bit of hassle in the long run.
#6
I don't experience your issue and I'm suprised that a problem would cause you to completely abandon the use of TGB.
Anyway, we're trying to help you here so if you still think TGB is something of use to you then please send along the script and we'll see if we can help. If not then good luck with whatever you choose to do.
Cheers,
Melv.
05/12/2008 (3:09 am)
Daniel,I don't experience your issue and I'm suprised that a problem would cause you to completely abandon the use of TGB.
Anyway, we're trying to help you here so if you still think TGB is something of use to you then please send along the script and we'll see if we can help. If not then good luck with whatever you choose to do.
Cheers,
Melv.
#7
Here's a copy of the email I sent you so that others can understand the thread content as well:
>>>>
I think you're issue here is one of perspective. The "OnCollision" callback isn't designed to give you a callback for each and every object that an object currently overlaps. The idea is that an object collides with an object, a solution is found and then (if you're iterating) you'll find another. Nothing says you won't find the same one again and again if you're not solving the collision e.g. have a response. The idea here is one of sequential collision/response/collision/response. The "OnCollision" callback is designed to give you information about the collision it's about to solve. If you disable the response you may well get it again. If the object is simultaneously overlapped multiple objects, you don't solve the collision then you'll get it multiple times.
Setting collision iterations to a crazy high number hurts performance and may well cause serious stalls in some circumstances. It doesn't control how many collisions you'll see. Also, an overlap is a bad situation. TGB uses swept collision detection to ensure that objects don't overlap. If you purposely overlap objects you're going against the automatic collision detection which will implicitly want to resolve the overlap.
You have to respect why systems are there and what their constraints are.
I created several routines that all use the internal collision system to do exactly what it seems you want to do. For instance, if you want to ask the question, "what objects will a certain object collide with in a certain time given all its collision setup" then you can use "%obj.CastCollisionList()" which will give you a complete list of objects. In your scene you can do this in a single call in the "OnUpdate" callback. This call supports stationary objects or objects that are moving in which case it'll use the time to sweep the direction the object is moving to detection a list of collisions which are returned in a time-order list from first to last.
If you only want the first then use "%obj.CastCollision()". The "OnCollision" callback is effectively the "CastCollision" which only returns the first collision encountered on the assumption that it's be solved either internally or by you in the callback.
So in summary, additionally turn-off the "OnCollision" and in the objects "OnUpdate" simply call "CastCollisionList" and you'll get a list of objects the object collides with (or will in the specified time). You can set the time to be "0.0" in which case the call only looks for current overlaps.
In the case of your scene you'd get a single collision object on the left/right and all objects in between would report two colliding objects.
Note that these calls use the internal collision system and are much more efficient than activating automatic collision-detection and supressing all forms of collision response. It won't work that way.
Hope this helps,
Melv.
05/15/2008 (8:46 am)
Daniel,Here's a copy of the email I sent you so that others can understand the thread content as well:
>>>>
I think you're issue here is one of perspective. The "OnCollision" callback isn't designed to give you a callback for each and every object that an object currently overlaps. The idea is that an object collides with an object, a solution is found and then (if you're iterating) you'll find another. Nothing says you won't find the same one again and again if you're not solving the collision e.g. have a response. The idea here is one of sequential collision/response/collision/response. The "OnCollision" callback is designed to give you information about the collision it's about to solve. If you disable the response you may well get it again. If the object is simultaneously overlapped multiple objects, you don't solve the collision then you'll get it multiple times.
Setting collision iterations to a crazy high number hurts performance and may well cause serious stalls in some circumstances. It doesn't control how many collisions you'll see. Also, an overlap is a bad situation. TGB uses swept collision detection to ensure that objects don't overlap. If you purposely overlap objects you're going against the automatic collision detection which will implicitly want to resolve the overlap.
You have to respect why systems are there and what their constraints are.
I created several routines that all use the internal collision system to do exactly what it seems you want to do. For instance, if you want to ask the question, "what objects will a certain object collide with in a certain time given all its collision setup" then you can use "%obj.CastCollisionList()" which will give you a complete list of objects. In your scene you can do this in a single call in the "OnUpdate" callback. This call supports stationary objects or objects that are moving in which case it'll use the time to sweep the direction the object is moving to detection a list of collisions which are returned in a time-order list from first to last.
If you only want the first then use "%obj.CastCollision()". The "OnCollision" callback is effectively the "CastCollision" which only returns the first collision encountered on the assumption that it's be solved either internally or by you in the callback.
So in summary, additionally turn-off the "OnCollision" and in the objects "OnUpdate" simply call "CastCollisionList" and you'll get a list of objects the object collides with (or will in the specified time). You can set the time to be "0.0" in which case the call only looks for current overlaps.
In the case of your scene you'd get a single collision object on the left/right and all objects in between would report two colliding objects.
Note that these calls use the internal collision system and are much more efficient than activating automatic collision-detection and supressing all forms of collision response. It won't work that way.
Hope this helps,
Melv.
#8
... just a few lines of script and unbelievably simple. This is where TorqueScript shines by getting TGB to do the hard work for you and let it just organise a few details. :)
Melv.
EDIT: typo
05/15/2008 (11:25 am)
... and here's the code that demonstrates determining every object that overlaps the "piece" objects in your demo each and every tick...function Piece::onLevelLoaded(%this, %scenegraph)
{
// We're not interested in "OnCollision".
%this.CollisionCallback = false;
// We want the "OnUpdate" call though.
%this.enableUpdateCallback();
}
function Piece::onUpdate(%this)
{
// Search for all objects overlapping object.
%colliderVector = %this.castCollisionList( 0 );
// Any colliders?
if ( getWordCount( %colliderVector ) > 0 )
{
// Yes, so spam the console.
echo( "Object:" SPC %this SPC "collides with Object(s):" SPC %colliderVector );
}
}... just a few lines of script and unbelievably simple. This is where TorqueScript shines by getting TGB to do the hard work for you and let it just organise a few details. :)
Melv.
EDIT: typo
#9
05/15/2008 (1:42 pm)
Thank you very much Melv. That makes perfect sense. Either I failed to read carefully or one sentence could be added to the onCollision() doc :)
Torque Owner Glenn Prince