- Home /
Ignoring collisions without using physics layers
Hi, I tried this question in Game Dev of Stack Exchange, but it might get more eyes out here...
I'm trying to ignore collisions between certain prefabs, but in this case I don't want to use layers since these are specific object pairs that I want to not collide, and creating a layer for each prefab would complicate the layer matrix more than I want to.
What I tried so far:
public void OnCollisionEnter(Collision collision) {
if (collision.gameObject.tag == "Bullet") {
Physics.IgnoreCollision(collision.collider, collider);
}
}
So I tried ignoring the collision in the OnCollisionEnter, but this only worked partially. The objects did go one through the other, but they both slowed down. My guess is that the first frame of the collision, the one that generated the call to OnCollisionEnter, was calculated regardless of the ignore command.
Any ideas how I can make all bullets not collide to one another, without putting them in a separate layer?
Yes, it's right there in the code I posted. The problem is that it doesn't work on prefabs, and I don't want to have to run it every instantiate a bullet with all other bullets. Doing it inside the collision is too late.
That's what I get for quickly commenting based on the title rather than reading the question in detail. Not directly answering your questions, but maybe you could use a bullet cache and reuse the bullets rather than instantiate and destroy them. That way you could do the IgnoreCollision() once when you fill the cache.
Thanks, that might be a nice solution, although I'll have to test the performance impact. What's the best way to keep bullets that are deactivated? Can you deactivate the script from running?
Anyway I'd like to see if anyone has a solution for preventing prefabs from colliding without using layers.
You want to set the GameObject holding the bullet to be inactive.
bullet.gameObject.SetActive(false);
Note at activation time or deactivation time you may need to set Rigidbody properties such as velocity and angularVelocity to Vector3.zero along with setting the activation property. If you don't, and if you are using AddForce() to move your objects, the objects will maintain their pre-cache state and take off in "random" angles or "random" speeds.
Answer by aldonaletto · May 16, 2013 at 03:26 AM
Depending on what should happen on collisions, you could set the projectile colliders to triggers and use the OnTriggerEnter event to process the collision yourself. This works fine when the projectile simply destroys the item hit, but probably will fail miserably if the goal is to produce an impact: a rock hitting a car, for instance, should throw the car away and modify its own trajectory as a consequence of the impact, but such effect is hard to emulate in your own code.
Turning back to the layers, you can set the collision matrix by script with Physics.IgnoreLayerCollision - this way all you would have to do is to set a different layer for each projectile type in the prefab script and disable collisions inside the this layer. A simple script like the one below could do the job:
public int myLayer = 11; // define the layer in the prefab script (8 to 31)
void Start () {
gameObject.layer = myLayer; // move the object to its layer...
// and ignore collisions between objects in it:
Physics.IgnoreLayerCollision(myLayer, myLayer, true);
}
Just set the layer number in the prefab script, so that all instances of this object will be in the same layer and ignore collisions between them. You don't need to define the layers in the Layer Manager - they already exist, but don't have names associated and thus won't appear in the Layer Collision Matrix.
-1.
The question states " I don't want to use layers" because of the number of layers.
This answer would not work if you have too many prefabs (there is a maximum of 32 layers you can use).