I want to put a script with an OnCollisionEnter function on a child object of another object that has a rigid body on it, but when the script is on the child object it doesn’t register.
To say it another way, I have two cubes, one cube is the child of the other cube and the root cube has a rigid body on it. OnCollisionEnter works on the root rigid body cube, but that same function put on the child cube, which is not rigid body and just has a collider, the onCollisionEnter function stops working.
Now it works when the root cube is not a rigid body. If both cubes just have colliders, the oncollisionenter works on the child colliders. But if the root object has a rigidbody, it seems to disable the OnCollisionEnter function for all it’s children.
Is this just how the Unity engine is? Or am I doing something wrong? How do I get the onCollisionEnter function to register on a child object or rigidbody?
Or do I need to do some workaround to only have such a function on the root cube?
The child colliders don’t register collisions with each other. This allows you to make combinations of colliders to model irregular shapes. Are your child colliders supposed to be free-moving relative to the parent?
The Collision object passed to OnCollisionEnter has a field representing the collider that was hit. If you have references to all your object’s colliders (say with public variables) you can compare them with the collider in the Collision object:-
var headColl: Collider;
var bodyColl: Collider;
// etc...
function OnCollisionEnter(coll: Collision) {
if (coll == headColl) {
// Do the head shot thing
}
}
I think I’m having the same problem and I think that this answer, while true, isn’t correct for what we’re looking for. Or maybe it was and my issue is different… either way…
I have a parent object with a rigidbody and a script.
Then I have a group of colliders as children of that. When OnCollisionEnter is called on the parent, coll will equal the collider of the other object that I hit. How can I get a reference to which child collider on the object running the script was hit?
var headColl: Collider;
var bodyColl: Collider;
// etc...
function OnCollisionEnter(coll: Collision) {
if (coll == headColl) {
if(coll.gameObject.name == "Blast(Clone)")
{
//SendMessageUpwards("Destroy");
Destroy(gameObject);
}
}
if (coll == bodyColl) {
Destroy(gameObject);
}
}
I have a human model which is the parent and has this script. And a simple capsule with capsule collider added as a child. It’s a bit away from the model so you can hit it easily. For the variable I selected the name of that capsule object. But when you shoot it, or hit it nothing happens.
I know this is an old thread, but I ran into the same problem recently.
andeee’s advice is not quite right, but eekllc is.
The gameObject, collider, and rigidbody in the Collision parameter all refer to the topmost object involved in the collision. To determine which sub-collider was hit, you need to look at the contact points’s thisCollider or otherCollider depending on whether you’re calling OnCollisionEnter on the target or the projectile.
I have one parent gameobject with a rigidbody and 100 child block objects with each a box colliders on it. My other object is a simple sphere which can bounce against the block structure. The sphere contains a rigidbody with sphere collider. The OnCollisionEnter Function from the sphere is reporting due reading the contact normals othercollider object often itself back instead of 1 of the 100 child blocks. With other words: othercollider is for my setup not reliable. Is there some more reliable way that tells me which block was hit and only includes 1 rigidbody for my block structure setup.
If you need more information about the other object then Physics provides then cast a ray to it with something like this (incomplete snippet). Please also note that the surface normal is not the same as the collision normal due for example more objects that are mostly hit (wall, floor and so on):
void OnCollisionEnter (Collision col)
{
m_breakOutPhysicsObjectTest = false;
for (int i = 0; i < col.contacts.Length; i++) {
if (Physics.Raycast (m_transform.position, (col.contacts[i].point - m_transform.position).normalized, out m_collisionhit, 5f, m_onCollisionRayLayerMask)) {
m_contactPointNormal = m_collisionhit.normal;
//Debug.DrawRay (m_transform.position, (col.contacts[i].point - m_transform.position).normalized, Color.red);
//Debug.Log (m_collisionhit.transform.gameObject.name);
//Debug.Break();
m_breakOutPhysicsObjectTest = true;
}
//Debug.Log (m_breakOutPhysicsObjectTest);
if (m_breakOutPhysicsObjectTest)
break;
}
I had a rigidbody and a collider on a root object, and the same on one of it’s children. I also had OnCollisionStay in scripts both on the root and the child. I expected OnCollisionStay to be only called on the child’s script (when the child collider hit something) but it was called on both the child script AND the root. This was not the behaviour I wanted and searching through all collision contact points seemed a bit like overkill.
I found a much simpler solution. I created a new child, and moved the collider from the root object to this new child. I also moved the corresponding script containing OnCollisionStay to this new child.
By moving all colliders off the root object, they each call OnCollisionStay on their respective scripts separately. There is no longer a script with OnCollisionStay on my root rigidbody object and so I’m no longer getting the double call, and can determine exactly which collider and child object is triggering OnCollisionStay.