- Home /
Collision Layer Ignoring Script Logic -- If && statements not working correctly
Hello!
I have a scripting problem that deals with ignoring collision layers. Briefly, I have two static gameobjects with mesh colliders and portions of their meshes overlap each other. This is necessary for my specific application and is fine otherwise. The problem is that i have a non-static rigidbody gameobject (with a box collider) which needs to 'bump into' these static colliders and when it does, I need code to run. So, this all works fine when collisions occur on the area where the mesh colliders are not overlapping each other---but causes extreme lag and poor performance when it collides in the overlapping areas.
My solution was to use a little If and && logic to activate/deactivate the collision layers such that only 1 collision layer (i.e., mesh collider) is active at any given time. I thought that this would work well, but the problem is that it keeps one layer activated and the other layer deactivated constantly (for example, layer 1 is active and layer 2 is ignored regardless of the logic). However, if I remove the gameobject that is associated with layer 1 from the scene, then layer 2 is no longer ignored (and vice versa).
Since it is partially working when I remove gameobjects from the scene, my guess is that the problem is with my C# code and the logic that I've used. I'm a beginner with both programming and Unity so any help offered will be informative and welcome.
Attached is the relevant portions of the code:
using UnityEngine;
public class CollisionForce : MonoBehaviour {
void OnCollisionStay(Collision collision)
{
//Layer 8 = Patch (one of the static mesh colliders)
//Layer 9 = Hemi (one of the static mesh colliders)
//Layer 10 = Peg (the rigidbody gameobject)
//if peg hits hemi and patch, ignore all hemi collider
if (collision.gameObject.layer == 9) // && collision.gameObject.layer == 8)
{
Physics.IgnoreLayerCollision (10, 9, false);
Physics.IgnoreLayerCollision (10, 8);
Debug.Log("test1");
}
//if peg hits patch only, ignore all hemi colliders
if (collision.gameObject.layer == 8) //&&collision.gameObject.layer != 9 &&)
{
Physics.IgnoreLayerCollision (10, 8, false);
Physics.IgnoreLayerCollision (10, 9);
Debug.Log ("test2");
}
//if peg hits hemi only, ignore all patch colliders
//if (collision.gameObject.layer == 9 && collision.gameObject.layer != 8)
//{
// Physics.IgnoreLayerCollision (10, 8);
// Debug.Log ("test3");
//}
}
I've tried both the commented out logic and the current logic and both behave the same way.
Answer by Bunny83 · Apr 23, 2019 at 03:49 PM
You have the wrong idea about boolean logic and you should look up the basics behind them. When you have an if statement like
if (collision.gameObject.layer == 9 && collision.gameObject.layer == 8)
Each condition is seperate from each other. The && operator only evalutates to true when both operands are true. Just by looking at this line you can immediately see that this can never ever happen. If the layer is 9 (so the first operand is true) then the layer can not be 8 at the same time. What you want is to use the "or" operator ||. You want that statement to be true when the layer is either 9 OR 8.
So it should be
if (collision.gameObject.layer == 9 || collision.gameObject.layer == 8)
Likewise in your second case the second condition is pointless. If the layer is 8 of course it will not be 9
edit
I just read your description carefully and just realised that what you want is something different. Though it's not really clear what actual behaviour you want . Your current code doesn't make too much sense. You use OnCollisionStay which is called every frame while you have a collision. Though when you collider with an object on layer 8 you disable the collisions with layer 8 so OnCollisionStay will no longer be called when the next physics update happens. So you get more like a trigger behaviour since once you touched that collider you disable the collision so you can no longer collider with it. However if the player is in an area where both colliders overlap, you would essentially switch between the two all the time. So what's your expected behaviour in those overlapping areas?
Thank you for your comments Bunny. The problem was that the layers are overlapping --i.e., the gameobjects exist in the same gamespace in some areas--thus the && statement. I assumed that the performance hits were co$$anonymous$$g when it was trying to process 2 layers occupying the same space. I will review and practice more boolean logic, and I appreciate your time and instruction.
Also, after reading more and then looking at the code for a while I thought about trying something and it worked. I added an additional on/off switch within both of the If statement to return it back to the original state:
void OnCollisionStay(Collision collision)
{
//Layer 8 = Patch
//Layer 9 = Hemi
//Layer 10 = Peg
//if peg hits hemi and patch, ignore all hemi collider
if (collision.gameObject.layer == 9) //&& collision.gameObject.layer == 8)
{
Physics.IgnoreLayerCollision (10, 9, false);
Physics.IgnoreLayerCollision (10, 8, true);
Debug.Log("test1");
Physics.IgnoreLayerCollision (10, 8, false); //** this line **
}
//if peg hits patch only, ignore all hemi colliders
if (collision.gameObject.layer == 8) //&&collision.gameObject.layer != 9 &&)
{
Physics.IgnoreLayerCollision (10, 8, false);
Physics.IgnoreLayerCollision (10, 9, true);
Debug.Log ("test2");
Physics.IgnoreLayerCollision (10, 9, false); //** this line **
}
This made the code work the way I needed it to and does not create any performance hits.
Yeah it is a little confusing. $$anonymous$$aybe try this (although this isn't the actual thing either): a spaceship (the rigidbody) that is trying to navigate inside (or outside) of a hollow asteroid (mesh collider 1) that has non-symmetrical, rotating holes (mesh collider 2) on its surface. The "asteroid" is actually a hollow, spherical object with circular holes on its surface. The "rotating holes" are actually larger than the circular holes such that they overlap with the "asteroid" surface and have a non-symmetrical cutout shape which is smaller that the circular holes on the surface of the "asteroid". $$anonymous$$aybe that just makes it more confusing! Anyways, the meshes overlap in small areas due to the geometries, although its the exact same geometry --thus, which the overlap occurs, I only want one collider to be recognized. And then, for efficiency, turning off the third collider when the collision is only occurring between two of the three relevant objects.
Actually, its still causing performance issues. I tested it with a gameobject (rigidbody) that I use for testing and it worked fine. I then tried it with the actual gameobject that I need to use for the application (also rigidbody) and it had massive performance hits again.
The difference between the two rigidbodies is that one of them is composed of 2 box colliders (image a cube with a rectangle on top of it) and this geometry can collide with both the mesh colliders at once. At least, I assume that it what is causing the problem. I'll be back tomorrow to work on it again and any insight that anyone can offer would be helpful. Thanks already for your attention Bunny.
Your answer
Follow this Question
Related Questions
Disable all collisions but one? 2 Answers
Collision that doesn't apply force between certain rigidbodies 0 Answers
Check if two objects are ignoring collision with each other 1 Answer
Death Condition ?? 1 Answer
Why does my player object decide to ignore colliders whenever he feels like it? c# 1 Answer