Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I'm making a racing game with cars in Unity. The car has a boost/nitro powerup. While boosting, I wouldn't want to be deviated when colliding with zombies, but I do want to be deviated when colliding with walls.

On the other hand, I don't want to ignore collision with zombies, because I still want to hit them on impact.

How should I handle this? Basically, what I want is for the car to not rotate when colliding with certain objects.

share|improve this question
add comment

4 Answers 4

Consider manipulating your layers at runtime.

Enabling/disabling collisions for certain objects with entire layers

Physics.IgnoreCollision and Physics.IgnoreLayerCollision allow you to disable collisions between two colliders, and between two layers, respectively.

If you want to exclude a specific collider from collisions, there's no built in way to do that. If you are using non-kinematic rigidbodies with non-trigger colliders, there will always be a response even if you try to filter out the responses by tag.

The way we accomplished this on our project was to create a layer named "Void". Void does not collide with anything at all.

Now you can temporarily disable a collider's collision by setting its layer to "Void", and re-enable it by restoring its old layer.

Here's the gist:

int oldLayer = -1;
int voidLayer;

void Start()
{
    voidLayer = 1 << LayerMask.NameToLayer("Void");
}

void DisableCollider(Collider col)
{
    oldLayer = col.gameObject.layer;
    col.gameObject.layer = voidLayer;
}

void EnableCollider(Collider col)
{
    col.gameObject.layer = oldLayer;
}

We did this specifically because enabling and disabling colliders that were children of rigidbodies can really screw things up in some circumstances. So you can't reliably disable part of a compound rigidbody collider, but you can reliably swap around the layer of one of the compound collider parts.

Now your specific situation

To reduce the impact zombie collision has on your car, consider making your zombies kinematic rigidbody triggers, or otherwise making their mass very very small (like float.Epsilon), so the impact has zero effect on the car's momentum. On impact, you can also do this layer switch, so that subsequent collisions aren't triggered, even if the first one applies a negligible force to the car body.

You could even switch them to a layer that just doesn't collide with the car.

You could also put another collider on zombies that get activated on ran-over. This way you can fake impact forces OnTriggerEnter. You can't get as accurate with it, but you can approximate where the contact normals may have been well enough to throw the zombie somewhere fun.

You have to ask yourself:

  • Do I want to be able to knock the ran-over zombies around with my car, or should they just play a death animation?

  • Do I care if the car's velocity and angular velocity are affected in smaller ways by hitting zombies?

share|improve this answer
    
Great answer, Michael! –  Blue 21 hours ago
add comment

I'm guessing you can check the names of the objects, or add a name value to the objects classes then check that?

bool boosting = false; //need a trigger in the game to set this to true.

function OnCollisionEnter(theCollision : Collision)
{   
    if (boosting == true)
    {
        if(theCollision.gameObject.name == "Zombie")
        {
              Debug.Log("Zombie hit during boost");              
        }
        else if(theCollision.gameObject.name == "Wall")
        {
              Debug.Log("Wall hit during boost");            
        }
    }
    else 
    {
        if(theCollision.gameObject.name == "Zombie")
        {
              Debug.Log("Zombie hit not in boost");              
        }
        else if(theCollision.gameObject.name == "Wall")
        {
              Debug.Log("Wall hit not in boost");                
        }
    }
}

Then just have another variable you can use to check for boosting and add that to the checks.

EDIT: added this variable in.

share|improve this answer
    
He knows how to be notified of collisions; he just doesn't want any action to be taken as a result. He wants to disable the built-in collision response in certain cases. –  Wackidev Jul 2 '12 at 21:57
    
Surely whatever happens when the collision is triggered goes between the brackets? I've not used unity before so I don't know but in cocos2d, and XNA its done like that. –  Lewis Jul 3 '12 at 0:54
    
Actually, Unity handles the collisions itself through PhysX. OnCollisionEnter is just a notification method; it isn't designed to handle the actual collision response. –  Wackidev Jul 3 '12 at 0:56
add comment

Call Physics.IgnoreCollision on all the zombies, passing the function the player object as well, when the car starts boosting. This will cause Unity to not react to any collisions between the player and the zombies. When the car is finished boosting, call Physics.IgnoreCollision again for each zombie, passing it the player object and false to cause collision-response to start again.

share|improve this answer
    
But that would mean they won't collide with anything else either. –  Paul Manta Jul 2 '12 at 14:26
    
I'll do some more research. The only thing I can think of is: perhaps you can ignore the collision by returning false from OnCollisionEnter? –  Wackidev Jul 2 '12 at 21:58
    
@Wackidev This is not the case. –  Rhys van der Waerden Jul 2 '12 at 23:49
    
@Paul I've edited my answer. –  Wackidev Jul 3 '12 at 14:02
add comment

I assume you are using the physics engine to do the 'deviation' automatically based on shape/mass when things collide together? if that is the case, then change the mass of your zombies to a very minimal value and they won't affect the car.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.