'Adding child to rigidbody makes it move
I have a parent object with a rigidbody (gravity disabled). With a script I am adding simple cubes with box colliders as children to this parent.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Test : MonoBehaviour
{
public GameObject prefab;
void Update()
{
if(Input.GetMouseButtonDown(0))
{
GameObject go = Instantiate(prefab, transform);
go.transform.localPosition = new Vector3(10f, 10f, 10f);
}
}
}
This works fine, but a slight movement of the parent object is visible everytime a cube is instantiated and parented. So eventually after adding quite a few cubes the parent moves even whole units from its original position, although the velocity is always Vector3.zero.
How does this movement happen and how do I prevent it?
Solution 1:[1]
So, it appears that the small movement of the rigidbody parent comes from a change in the centre of mass. By moving or instantiating objects as childs this value has been changed as it states in https://docs.unity3d.com/ScriptReference/Rigidbody-centerOfMass.html:
If you don't set the center of mass from a script it will be calculated automatically from all colliders attached to the rigidbody. After a custom center of mass set, it will no longer be recomputed automatically on modifications such as adding or removing colliders, translating them, scaling etc. To revert back to the automatically computed center of mass, use Rigidbody.ResetCenterOfMass.
Finally, as solution I just set the local center of mass to a fixed value.
rig.centerOfMass = Vector3.zero;
I am quite happy with this solution, because this also changes the center of rotation. Still I am not quite sure why it adds a movement on a change in the center of mass, because I don't see why that would be realistic behaviour.
Also there is a difference between rigidbody.position and transform.position. By using solutions such as commented under the question:
- Unparent, move child, parent again
- Disable child, move child, enable child again
- Disable the child's collider, move child, enable it again
...it is possible to keep the transform.position the same, but rigidbody.position will still change. This difference between both values persists as long as the rigidbody is asleep. Waking it up e.g. by calling Rigidbody.Wakeup() will sync both values again. Due to a difference in both values even things like a raycast can fail, although the ray might be hitting the spot where the meshes are actually drawn and just the physics engine thinks they are somewhere else. Also waking up again looks ugly because the mesh snaps back into place were it should be to match the rigidbody.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | janos_ |
