14
\$\begingroup\$

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.

\$\endgroup\$

5 Answers 5

7
\$\begingroup\$

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 = 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?

\$\endgroup\$
0
1
\$\begingroup\$

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.

\$\endgroup\$
4
  • \$\begingroup\$ But that would mean they won't collide with anything else either. \$\endgroup\$
    – Paul Manta
    Jul 2, 2012 at 14:26
  • \$\begingroup\$ 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? \$\endgroup\$
    – Wackidev
    Jul 2, 2012 at 21:58
  • \$\begingroup\$ @Wackidev This is not the case. \$\endgroup\$ Jul 2, 2012 at 23:49
  • \$\begingroup\$ @Paul I've edited my answer. \$\endgroup\$
    – Wackidev
    Jul 3, 2012 at 14:02
0
\$\begingroup\$

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.

\$\endgroup\$
3
  • \$\begingroup\$ 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. \$\endgroup\$
    – Wackidev
    Jul 2, 2012 at 21:57
  • \$\begingroup\$ 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. \$\endgroup\$
    – Lewis
    Jul 3, 2012 at 0:54
  • \$\begingroup\$ Actually, Unity handles the collisions itself through PhysX. OnCollisionEnter is just a notification method; it isn't designed to handle the actual collision response. \$\endgroup\$
    – Wackidev
    Jul 3, 2012 at 0:56
0
\$\begingroup\$

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.

\$\endgroup\$
0
\$\begingroup\$

There are two classes of answers here:

  1. Ignoring or disabling collisions
    • These solutions will not solve the problem, he wants the zombies to go flying when hit.
  2. Changing mass:
    • This is a good approach. Don't forget to also change Inertia accordingly.
      • You could alternatively change the cars Mass and Inertia when boosting (we do this to reduce the impact of all non-kinematic objects on a car when boosting)
      • This should not effect the road or walls assuming that those are kinematic.

Hope this helps!

\$\endgroup\$
2
  • \$\begingroup\$ Two of the existing answers from six years ago already recommend the mass-based approach you're suggesting here. Is there some new strategy you want to add? \$\endgroup\$
    – DMGregory
    Oct 29, 2018 at 13:06
  • \$\begingroup\$ I apologize, I am not able to upvote yet and I wanted to ensure that Paul Manta was not lead astray. \$\endgroup\$
    – Avatar
    Nov 8, 2018 at 1:39

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .