Game Development Community

CastCollision

by Christian Rousselle · in Torque Game Builder · 04/24/2008 (4:22 am) · 7 replies

The function for castcollision includes this code:

// Check Object unless it has its collisions suppressed and isn't receiving collisions.
        if ( !pDstObject->getCollisionSuppress() && pDstObject->getCollisionActiveReceive() )
        {
         ...
        }

As far as I understand this code objects that are not receiving collisions are not checked for collisions by the current object. Maybe I am totally misunderstanding the collision concept but why does the destination object need to have collision receive enabled? Is not collision send what is important for this check?

Thanks

#1
04/24/2008 (6:25 am)
A Collision Sender and a Collision Receiver are always required for a collision event to occur.
#2
04/24/2008 (6:35 am)
Thanks.

Yes but in my case the object that calls castCollision() has collisions send/receive activated (%this.setCollisionActive(true, true);) but the object that is close to the casting object only has send activated (%this.setCollisionActive(true, false);) In this case castCollision does not find this object. If I change the code to

if ( !pDstObject->getCollisionSuppress() && pDstObject->getCollisionActiveSend() )
        {
          ... 
        }

it works like I think it should. But I am not sure if I misunderstand how collisions work.
#3
04/24/2008 (12:01 pm)
Christian,

The potential unidirectional nature of collisions can be very confusing and I originally came up with the implementation idea so you can kick me if it's confusing. ;)

To really appreciate the concept here you have to understand (and you probably do but it's for others reading too) that the collision processing is done object by object. In other words each object takes its turn to move, find collisions and respond to them.

Given the above then, when an object needs to move, it sweeps the direction determined by its current velocity. Assuming then that it encounters some objects which absolutely will collide, it determines if those objects are setup in such a way that the collision is valid. If so you get a response else it's just ignored.

"CastCollision" and "CastCollisionList" essentially simulate the search described above in that they both use the current objects collision setup/velocities and return a single object or a list respectively.

So to answer your question...

The decision on what is a valid collision is based upon a simple formula in that the object "sending" the collision will only collide with objects "receiving" collisions. Also, the object will only collide with objects with the specified collision group/layer.

In this setup you can have a unidirectional collision. This means that I could setup a player that hits an object and responses accordingly but not have the object collide with the player when it comes to its turn to move.

What this boils down to (after collision group/layer checking) is that the sending object can only collide with objects receiving them. Objects throw (send) the collision ball and only objects catching (receiving) the collision ball make a collision.

Bad analogy but the best I could come up with quickly. :)

It is possible to put send/receive on both objects. If you do that then the only thing that determines whether objects collide is the collision group(s)/layer(s) specified by the collision sender. The caution here though is that sending collisions costs in performance terms so only send collisions where you have to.

I hope that helps a little.

Melv.
#4
04/24/2008 (12:43 pm)
Thanks Melv,

it is always helpful to get an answer. Since I am not sure if you understood my problem correctly (although I suppose you did and I am not able to fully get your answer) I attached two screenshot and tried to explain what I am currently doing.

www.codecoach.de/GG/collisioncast1.jpg
www.codecoach.de/GG/collisioncast2.jpg
The player ship has both collision send and receive enabled since the player needs to send collisions into the system, so that other objects know when the player collided with other object. These object will react (e.g. explode). The player receives collisions by other objects so that the player ship can explode if it hit somethig bigger.

Enemies also have send/receive enabled (same reasons as for the player)

The Tiles (cave/landing) only have send collision active since they do not care if they were hit but simply tell other objects that they hit a wall (which leads to the object being destroyed) or in case of the landing tile to tell the player ship that it can land there.

There is no problem with this setup, everything works as expected.

Now I want to be able to give enemies the ability to move around by themselfs. So the bottom enemy moves right and calls castCollison. The idea is to move up once a cave tile gets close. The problem is that the cave tile does not have receive enabled and therefore castCollision does not find anything. If I change the code like I described it works as I expect.
#5
04/24/2008 (12:59 pm)
A picture paints a thousand words. :)

The problem here is that your tiles (cave/landing) are using send collisions to tell other objects that they hit. This is where the problem lies and although it sort of works, it's expensive and logically reversed, let me explain.

First of all, having all these presumably stationary objects sending collisions is very expensive but the real problem is that you'll only know when an object hits the scenery when the objects (enemies and player) overlap it which definately isn't what you want. This is because the tiles are not moving and they only check the collision polygon (green above). Objects that move use the nice swept-collision detection which looks for collisions over time given the current velocity. Indeed, "castCollision" and "castCollisionList" use this sweep system as you specify the time to sweep. You won't see objects that are not receiving collisions!

The answer then is to set all static scenery to receive collisions only. This takes zero processing during each frame. Get the objects that want to collide with the scenery (presumably these are moving) to send collisions.

This is indeed one of the primary reasons why it's nice to have seperate send/receive. Static scenery shouldn't take any collision processing time (not send collisions) but receive only. Objects that could collide with it (enemies/player) should and they should be sending the collision.

The primary reason is that your scenery is nearly always at least an order of magnitude more in number than the player/enemy objects so you want them to take little/no processing.

Either using the built-in physics or using "castCollision" on an enemy/player object will see the tiles if you set tiles to receive.

In summary then:

Player/Enemies = Send + Receive
Tiles = Receive Only

If this is confusing then please say and I'd be happy to try to explain it another way. :)

Melv.
#6
04/24/2008 (2:10 pm)
Thank you. This is understandable. One last thing. This means that I have to handle collisions between tiles and moving objects in the onCollision() function of the tiles? Something like

function TileClass::onCollision(%srcObj, %destObj...)
{
   if(%destObj.class $= "Enemy")
   {
      %destObj.SomethingCollidedWithMe();
   }
   else if(%destObj.class $= "Player")
   {
      ....
   }
}

Or is there a better way without the necessity of this large if/switch expression?
#7
04/24/2008 (3:16 pm)
OnCollision will be called for both the sender and the receiver, so you shouldn't need to do %destObj.SomethingCollidedWithMe(), since you can handle the event in the %destObj's oncollision.

But, that basic idea, having a switch in oncollision to handle different collision objects differently, is exactly what I'm doing. I'm not aware of a better way, but would be curious if other developers have had any ideas.