Game Development Community

OnCollision not respecting the layer mask (only in behaviors)

by Diego Santos Leao - GameBlox Studio · in Torque Game Builder · 03/31/2008 (8:26 pm) · 11 replies

I have a behavior that uses an "onCollision" callback. The problem is that "onCollision" is called even when there are collisions with a layer that I have excluded from check (through a layer mask).

I'm sending a link to the image showing that the "%dstObj" object is in layer "31", although the layer mask of the owner of the behavior is going only until "30" (watch the debug window right bellow)... The onCollision method shouldn't be called on collisions on layer "31"!

http://img220.imageshack.us/img220/4250/shouldntbehereji8.jpg
(I rasured the code inside the method to avoid going off topic about the contents of it)

#1
04/01/2008 (10:38 pm)
This would be correct. Behaviors are inherited from the simobject class. Simobject does not support collisions. Collisions are defined by the t2dsceneobject class, which would make sense because a behavior is not an object in the scene but a control(behavior) of a scene object. You should be doing your collision callbacks on the parent object your behavior is attached to.

I hope that makes sense.
#2
04/02/2008 (12:10 am)
I'm not sure what is causing this for you, but Lewis' comment is incorrect.

It's definitely fine to handle oncollision callbacks in a behavior. If you couldn't, then it would be much harder to make it a "behavior". Its not a sceneObject, but it can handle its owning sceneObject's oncollision callbacks ( Eg. it is cc'd to the behavior ).
#3
04/02/2008 (8:01 am)
@James
I stand by my comment. You can create a callback and yes it will be called, but as you stated the behavior is "cc'd". Since you used the term cc'd (which by the way caused my wife and I to have a lengthy discussion about*) lets use an analogy here.

We both receive an email from collision, collision happens to be chinese so the email is written in chinese. I(sceneobject) can read chinese, so the letter makes perfect sense to me, you(behavior) on the other hand do not understand chinese, so you have the same email I have but cannot process it because you don't understand it.

I set my oncollision callback in my behavior but it does not have the necessary tools to process the data (i.e layermasks, groupmasks and active send, active receive, etc) because it was the parent that actually collided and is simply passing me the info that it collided. The parent collided with something and triggered the event and the behavior simply processes that event without the benefit of the same filters that the parent has. The behavior is NOT inherited from the parent and therefore does not have the same attributes that the parent has. Consider it more like it is mounted to the parent and can access the same information the parent has but does not process it in the same way the parent object does.

I am not sure the effort it would require to modify the engine to trigger the oncollision in the behavior only if the parent processed it fully.

So yes you can process collisions but with limitations. This is purely theoretical at the moment as I haven't dug completely through the source yet to verify my hypothesis but I think it is a pretty solid theory. When I have time I will dig into the source and post the details of my findings here.


*I am an Email Engineer by day and my wife pointed out to me the term cc refers to "carbon copy" which is such an antiquated term. It stuck me as funny how we tend to carry things like this forward and just repurpose them. I mean really when was the last time anyone really used carbon paper to make a copy, but yet we throw the term term around daily.
#4
04/02/2008 (8:45 am)
I thought it was a bit of witty word choice my self '-)

We will have to look at the source closer to be sure on this issue.
#5
04/02/2008 (10:11 am)
A great find... some notes:

First I'd like to say that behaviors are intended to receive the onCollision callback of the object. Basically behaviors were initially envisioned to handed replicated callbacks from the base object, onCollision being one of the most useful... that way one behavior can trigger a particle effect on collision, while another could trigger a sound... modularizing coding, including an increase in reuse (one onCollision audio trigger with a field for the audio could be used for every onCollision audio effect, if done right.

I did some research into this. I was able to reproduce the effects... also note that the collision callback in these circumstances was not only called on the behavior but on the objects class as well. I also found the reason why it was doing this (and was able to work around it also). Here was my setup

moving and colliding object:
layer: 5
collision layers: all but 31 (just like the OP)


destination object:
layer: 31

I had the same results, both on the behavior on the moving object and it's class. Setting it up like this silenced it:


moving and colliding object:
layer: 5
collision layers: all but 31 (just like the OP)


destination object:
layer: 31
collision layers: 5 [b]or[/b] setting it to not "Send Collision" (requests)


So apparently the problem happens when the destination object is set up to collide with the source object, this will then trigger a collision on the source object as well. Definitely weird, not how I would've guessed, though I can understand why it's doing what it's doing as well.
#6
04/02/2008 (10:19 am)
In the source code it definitely checked for the collision callback for both the source and destination objects when a collision occurs:

// Check for Script Collision-Callbacks for both Source/Destination.
    // Source...
    if ( pSrcObject->getCollisionCallback() )
    {
        pSrcObject->onScriptCollision( pCollisionStatus );
    }

    // Destination (only if receive collisions are active).
    if ( pDstObject->getCollisionCallback() && Con::getBoolVariable( "$pref::T2D::dualCollisionCallbacks", true ) )
    {
        // Receive Collision Status.
        t2dPhysics::cCollisionStatus receiveCollisionStatus;
        // Reverse Collision Status.
        t2dPhysics::reverseCollisionStatus( pCollisionStatus, &receiveCollisionStatus );

        // Script callback.
        pDstObject->onScriptCollision( &receiveCollisionStatus );
    }
#7
04/02/2008 (10:21 am)
As you can see in the above source code it checks

$pref::T2D::dualCollisionCallbacks

before calling the destination callback though, so just confirmed that setting

$pref::T2D::dualCollisionCallbacks = false;

prevents this "dual" callback case :)
#8
04/02/2008 (10:34 am)
@Mathew
Aha, looks like you found the root of the issue. I've seen these types of questions so many times -- it would be GREAT to have this kind of info as part of the "Collisions" feature tutorial. Its not that collision sending/receiving/callbacks is badly designed -- it isn't -- its just highly unintuitive at first.

@Guy
So, whether the oncollision callback is defined in a behavior's namespace or a sceneObject's namespace, you can still, in some situations, get callbacks with a %dstObj that is not in your CollisionMask(s).

In Summary:

The CollisionLayerMask and CollisionGroupMask of an object affect what other object's it can SEND collisions to. It does not affect what other objects can SEND IT collisions ( ie. RECEIVE ). Since onCollision happens for both sending and receiving objects, this means you can get an oncollision callback with a dstObj that is not in your collision masks.

So, for two objects that both send and receive, making a "one-way" collision mask is not an effective way of filtering oncollision callbacks. Instead you can always test the %dstObj.class in onCollision for both, one does nothing, the other does what you want!
#9
04/02/2008 (10:36 am)
Ignore the last paragraph of what I just said '-)

@Mathew
Holy crap, who knew that was there??
#10
04/02/2008 (4:16 pm)
Nice to see this cleared :) If I understood correctly the current way to set the layer mask to disable all collision between two objects (without changing the send or receive status of my objects) is to create a mask that disables that particular layer on both the "colider" and "colided" objects, right?
#11
04/02/2008 (9:53 pm)
That sounds right. Note that you can also use the graph group mask, not just layers.