- Home /
Having more than one collider in a GameObject?
Can we create more than one colliders in a GameObject and then access those colliders as an array or something?
I have one gameobject with a box colliders that i'm using for physics. However, i want a second collider, doubled in size, to be the colliders that my "mouse clicking code" will see. One collider is used for physics, the other one for the mouse to raycast properly.
I have two colliders on my Game Object, bowling ball. I have both a sphere collider and a mesh collider. The reason why I have the mesh collider is because I need the convex property to be set on otherwise the bowling ball will not allow me to send through giant pipes (cylinders). The sphere collider is there to collide with the terrain when under gravity as the game start. The only problem is that even if I set the rigidbody component on that bowling ball and have the Gravity on, it still falls through the terrain on some level. It could be that I have the starting position too high above the floor?
There's no reason to have both. Remove the mesh collider; all you need is the sphere collider. Also, if you have a question, you should post it as such and not as a comment to a different question.
Hey Eric5h5, thanks for the reply. Unfortunately when I stick with only the sphere collider it bounces back from the cylinder opening when it should go through it. Inside the cylinders is where the majority of the game happens. Initially the post was intended to be a comment, but it ended with a question.
Answer by Eric5h5 · Nov 24, 2011 at 05:06 AM
You can add multiple colliders to the same object, but they have to be different types. e.g., sphere + box = fine, box + box = impossible. Also all colliders will be used for the same purpose; you can't have one collider be for physics and one not. You can add multiple colliders of the same type using children, but again all of them count as the same collider of the parent (known as compound colliders). In order to have two different colliders act in different ways, you must use two separate gameobjects.
can Collision/Trigger for more than one collider in one gameObject be detected? meaning suppose i have Box + Sphere collider. can i know what is colliding/triggering the box collider and what is colliding/triggering the sphere collider?
Yep. also want to know if it's possible to distinguish which collider of the same object was entered: box or circle
I used up to 10 box colliders per building and didn't have any issue, what issues would it cause?
Note that this answer was written in 2011 and is no longer accurate, since Unity upgraded PhysX.
Answer by s4b3r_t00th · Aug 19, 2014 at 05:10 AM
The way I got around this was to use the layers system. If you put the one collider on a gameobject then put the second on a child of the game object you can set the layer on the child to something like IgnoreRaycast which will make it invisible to the physics engine. Which is really useful in certain aspects. Like mmmPies problem, you could use the collider that you put in the IgnoreRaycast layer as range. So you'd make it a sphere in your script you use a collision between that collider and the player to pick up the item. Granted mmmPies found his own solution but when you pickup script relies on colliders this works.
This is exactly what I need. I want a sphere collider for range, and a box or mesh collider for my spaceship for physics collision. Can you give an example of how this is implemented?
Answer by ShawnFeatherly · May 04, 2016 at 03:14 AM
Found an answer to this here. The answer was leveraging the type of the colliders on the gameobject to determine what to do:
void OnCollisionEnter2D(Collision2D collision)
{
if (collision.collider.GetType() == typeof(BoxCollider2D))
{
// do stuff only for the box collider
}
else if (collision.collider.GetType() == typeof(CircleCollider2D))
{
// do stuff only for the circle collider
}
}
or using an array index, such as var collider1 = GetComponents<BoxCollider>()[0];
To generate the 3D version of the code above evaluate this C# [code as a literal].Replace("2D","").Replace("CircleCollider","SphereCollider");
.
Answer by Mmmpies · Jul 08, 2014 at 09:26 AM
Bumping this because I came up with a simple solution. I wanted to fire an arrow and have it stick in whatever it hit (so it needed a trigger collider to do that) and I gave it box collider so it didn't fall through the terrain.
Also wanted a 5 meter radius collider so I could either pickup automatically or display an icon to give the choice to pick up the arrow on the floor. Came to this post hoping for a solution to multiple colliders in one gameobject, then I realised I'd seen something similar in the Burgzerg treasure chest tutorial. So I used that:
public bool AlwaysPickup; // If yes picks up on collision (small item like arrows). If no displays pickup icon.
private Transform _itemTransform;
private GameObject _player;
private float _inRange;
private bool _triggered;
private bool _released;
void Awake()
{
_itemTransform = transform;
_player = GameObject.FindGameObjectWithTag("Player");
_inRange = 5f;
_triggered = false;
}
void Update()
{
if(_player == null) // Probably wasteful. Consider changing the order of the scripts so the Player is available
{
_player = GameObject.FindGameObjectWithTag("Player");
}
if(Vector3.Distance(_itemTransform.position, _player.transform.position) < _inRange)
{
if(!_triggered)
Trigger ();
}
else if (!_released)
Released();
}
private void Released()
{
_triggered = false;
_released = true;
Debug.Log ("Exited range at: " + Time.time);
if(!AlwaysPickup)
{
Debug.Log ("Remove display pickup icon here");
}
}
private void Trigger()
{
_triggered = true;
_released = false;
Debug.Log ("Entered range at: " + Time.time);
if(AlwaysPickup)
{
Debug.Log ("I should handle picking up the item here");
}
else
{
Debug.Log ("Put display icon here");
}
}
Answer by unity_1H0rD1r0vA4vPQ · May 24, 2020 at 11:34 AM
You can attach multiple empty gameObjects with Coliders to your main gameObject, and attach to them simple script, which triggers Actions, which can be subscribed by parent gameObject.
Each child gameObject with collider will have the same script:
{
using UnityEngine;
using System;
public class Collision2D_Proxy : MonoBehaviour
{
public Action<Collision2D> OnCollisionEnter2D_Action;
public Action<Collision2D> OnCollisionStay2D_Action;
public Action<Collision2D> OnCollisionExit2D_Action;
private void OnCollisionEnter2D(Collision2D collision)
{
OnCollisionEnter2D_Action?.Invoke(collision);
}
private void OnCollisionStay2D(Collision2D collision)
{
OnCollisionStay2D_Action?.Invoke(collision);
}
private void OnCollisionExit2D(Collision2D collision)
{
OnCollisionExit2D_Action?.Invoke(collision);
}
// etc ...
}
Parent gameObject needs just to subscribe required events:
public class CharacterBehaviour : MonoBehaviour
{
private Collision2D_Proxy firstCollider;
private Collision2D_Proxy secondCollider;
void Start()
{
// subscribe collision events
firstCollider = transform.Find("FirstChildGameObjectName").GetComponent<Collision2D_Proxy>();
firstCollider.OnCollisionEnter2D_Action += firstColider_OnCollisionEnter2D;
secondCollider = transform.Find("SecondChildGameObjectName").GetComponent<Collision2D_Proxy>();
secondCollider.OnCollisionExit2D_Action += secondColider_OnCollisionExit2D;
}
private void firstColider_OnCollisionEnter2D(Collision2D collision)
{
print("first collider OnCollisionEnter2D collision" );
}
private void secondColider_OnCollisionExit2D(Collision2D collision)
{
print("second collider OnCollisionExit2D collision" );
}