I have 3(Three) BoxCollider2D components where 2(two) have OnTrigger checked in my Object and both have different functions. Due to having OnTrigger on both, the projectiles I am casting collide with the wrong collider and instead activate that function. Is there a way to ignore 1(one) OnTrigger collider? I have already tried Layer-based collision detection and set up a layer. Unfortunately, the object now collides with the collider which eliminates the player on collision
CodePudding user response:
However, there are several ways to solve this problem. All kinds of physics.checks
as well as raycasts
but this code helps you to ignore the obstacle collider.
public Collider2D playerCollider;
public Collider2D obstacleCollider;
public void Start() => Physics2D.IgnoreCollision(playerCollider, obstacleCollider);
CodePudding user response:
I have a very simple script I use to handle collisions in my games. It's very easy to setup because it makes everything drop and draggable, which is a much easier way to program.
Below is the script and below that is instructions on how to use. Note it is a layer based system, but you can select multiple layers.
[System.Serializable]
public class TriggerEvent : UnityEvent<Collider> { }
[System.Serializable]
public class CollisionEvent : UnityEvent<Collision>{ }
public class EnterEvent: MonoBehaviour
{
public TriggerEvent TriggerEnteredEvent;
public CollisionEvent CollisionEnteredEvent;
[SerializedField]private LayerMask validLayers;
// Initalize Event System
void Awake()
{
if (OnTriggerEnter == null)
{
TriggerEnteredEvent = new TriggerEvent();
}
if (OnCollisionEnter == null)
{
CollisionEnteredEvent = new CollisionEvent();
}
}
// Called if transform is a trigger
void OnTriggerEnter(Collider collider)
{
if (validLayers == (validLayers | 1 << collider.gameObject.layer))
{
TriggerEnteredEvent?.Invoke(collider);
}
}
// Called if transform is not a trigger
void OnCollisionEnter(Collision collision)
{
if (validLayers == (validLayers | 1 << collision.gameObject.layer))
{
CollisionEnteredEvent?.Invoke(collision);
}
}
}
This is how it would work, and in this example I will be "coding" it from the perspective of a Bullet. Basically I want to check if I (The Bullet) hits either the terrain or an enemy then call the relevent funcitons in the Bullet class respectively. Obviously if I hit an enemy I want to deal damage.
So this will be my example bullet class
public class Bullet : MonoBehaviour { public int BulletDamage = 10; public int BulletSpeed = 5;
void FixedUpdate() => transform.position = Vector3.Lerp(transform.position, transform.position transform.forward * speed * Time.deltaTime, 1f);
public void OnEnemyHit(Collision collision)
{
// Try to get the enemy script
Enemy enemy = collision.gameObject.transform.GetComponent<Enemy>();
if (enemy != null)
{
enemy.DealDamage(this.BulletDamage);
}
}
public void OnTerrainHit(Collision collision)
{
Destroy(this.gameObject);
}
}
- Add the EnterEvent script to the bullet.
- Add the Bullet Script to the bullet.
- There will be a space on the Inspecter where you can add your events. It should have a Plus and Minus in the top right corner. Press the plus.
- From the inspector drag the bullet in game GameObject to the open space provider.
- In the dropdown to the right, click on it, look for the Bullet Script, and select the OnEnemyHit function from it.
- Create another event, do the exact same, but this time select the OnTerrainHit funciton instead - now but would be called in the order you added them.
- Just underneath the event system should be the be able to see a dropdown for the Layers. Select all the layers you want your bullet to interact with. In this case it will be the Enemy and Terrain.
Finally remember to setup your layers properly. Ensure the Enemy has an Enemy Layer, the Terrain has a Terrain Layer, Bullet bullet layer and Player has a Player Layer