Strange "lock" when setup colliders and rigidbody by scripting...

Dear all,

I am facing a strange problem while setup BoxCollider and WheelColliders on a rigidbody character through scripting. All colliders are well installed on the rigidbody in the game view.

If i add ridigbody component before colliders some axis of character seams to be "locked"

The effect disappear when i change a value into rigidbody inspector.

My first workaround was to setup colliders (collider components) before physics (add(rigidbody)).

void Awake() {
    setupColliders();
    setupPhysX();
}

And in this it work well ! But i got this message:

WheelCollider requires an attached Rigidbody to function.

How i can get my script working properly by setting up rigidbody before colliders?

void Awake() {
    setupPhysX();
    setupColliders();
}

My full code is just under :)

Thanks for support,

Best regards,

Thomas

public class CharacterBehave : MonoBehaviour {

/**
 *  Attributes 
 */
// Wheels
private WheelCollider   wheelFL;
private WheelCollider   wheelFR;
private WheelCollider   wheelRL;
private WheelCollider   wheelRR;
private WheelCollider[] wheelsArray;    // Reference all wheel in an array
private float           steeringAngle;

public float            jumpForceCoeff;
public bool             inAir;
//public float            riderMass = 70.0f;

/**
 *  Methods
 */

void Awake() {
    setupColliders();
    setupPhysX();
}

void Start () {

}

void Update () {
}

void FixedUpdate() {

    InputListener();

    if (Input.GetKeyUp("space"))
    {
        Debug.Log("Jump");

        rigidbody.AddRelativeForce(Vector3.up * rigidbody.mass * jumpForceCoeff);
    }

}

public void InputListener() {

    float axisX = Input.GetAxis("Horizontal");

    steeringAngle = axisX * 1.4f;

    wheelFL.steerAngle = steeringAngle;
    wheelFR.steerAngle = steeringAngle;
    wheelRL.steerAngle = -steeringAngle;
    wheelRR.steerAngle = -steeringAngle; 

}

public void setupPhysX() {
    gameObject.AddComponent("Rigidbody");   
    rigidbody.mass = 70;
}

public void setupColliders() {

    /**
     * Creating Colliders objects
     */
    GameObject rootColliderObj = new GameObject("Colliders");   // Creating root Collider GameObject
    rootColliderObj.transform.parent = this.transform;
    rootColliderObj.transform.localPosition = Vector3.zero + Vector3.up * -0.5f;

    GameObject baseColliderObj = new GameObject("base");        // Creating baseColliderGameObject and affect it to Rider
    baseColliderObj.transform.parent = rootColliderObj.transform;
    baseColliderObj.transform.localPosition = Vector3.zero;

    GameObject bodyColliderObj = new GameObject("body");         // Creating baseColliderGameObject and affect it to Rider
    bodyColliderObj.transform.parent = rootColliderObj.transform;
    bodyColliderObj.transform.localPosition = Vector3.zero;

    /**
    * Create base
    */
    BoxCollider baseCollider =  baseColliderObj.AddComponent("BoxCollider") as BoxCollider;
    baseCollider.size = new Vector3(    transform.localScale.x * 2,
                                        transform.localScale.y / 3,
                                        transform.localScale.z * 7);

    baseCollider.center = new Vector3(0, transform.localScale.y * -4.0f, 0);  // Set baseCollider position

    // Create bodyBox
    BoxCollider bodyCollider = bodyColliderObj.AddComponent("BoxCollider") as BoxCollider;
    bodyCollider.size = new Vector3(    transform.localScale.x * 2,
                                        transform.localScale.y * 7,
                                        transform.localScale.z);

    /**
    *  Create 4 Wheels and affect them
    */
    // Create gameObject for wheels
    GameObject[] wheelObj = new GameObject[4];
    wheelObj[0] = new GameObject("wheel_" + "FL");
    wheelObj[1] = new GameObject("wheel_" + "FR");
    wheelObj[2] = new GameObject("wheel_" + "RL");
    wheelObj[3] = new GameObject("wheel_" + "RR");

    // Parent to base and Create WheelColliders 
    wheelsArray = new WheelCollider[4];

    for (int i = 0; i < wheelObj.Length; i++) {
        wheelObj*.transform.parent = baseColliderObj.transform;*
 <em>wheelsArray _= wheelObj*.AddComponent("WheelCollider") as WheelCollider;*_</em>
 <em><em>_wheelObj*.transform.localPosition = Vector3.zero;*_</em></em>
 <em><em>_*}*_</em></em>
 <em><em>_*// Affect wheels to position naming convention Front/Rear/Left/Right*_</em></em>
 <em><em>_*WheelFL = wheelsArray[0];*_</em></em>
 <em><em>_*WheelFR = wheelsArray[1];*_</em></em>
 <em><em>_*WheelRL = wheelsArray[2];*_</em></em>
 <em><em>_*WheelRR = wheelsArray[3];*_</em></em>
 <em><em>_*// Placing the wheels*_</em></em>
 <em><em><em>_float wheelYPlacement = (bodyCollider.size.y / 2.0f * -1) + baseCollider.size.y - 0.1f;_</em></em></em>
 <em><em>_*WheelFL.center = new Vector3(baseCollider.size.x / -2, wheelYPlacement, baseCollider.size.z / 2);*_</em></em>
 <em><em>_*WheelFR.center = new Vector3(baseCollider.size.x / 2, wheelYPlacement, baseCollider.size.z / 2);*_</em></em>
 <em><em>_*WheelRL.center = new Vector3(baseCollider.size.x / -2, wheelYPlacement, baseCollider.size.z / -2);*_</em></em>
 <em><em>_*WheelRR.center = new Vector3(baseCollider.size.x / 2, wheelYPlacement, baseCollider.size.z / -2);*_</em></em>
<em><em>_*}*_</em></em>
<em><em>_*```*_</em></em>
<em><em>_*<p>}</p>*_</em></em>

Here's a weird hack I had to do for some physics init myself: After colliders have been placed on the object with rigidbody (have the rigidbody added first), you can enable and disable the rigidbody. This seems to force a recalculation of inertia etc.

Try adding the rigidbody, wait one fixed frame, then add the WheelColliders. You should move the function calls SetupPhysX() and SetupColliders() to FixedUpdate, then use some flags or counters to ensure the correct order:

var initCounter = 0;

function FixedUpdate()
    {
    if (initCounter == 0) SetupPhysX();
    if (initCounter == 1) SetupColliders();
    initCounter++;
    if (initCounter < 2) return;

    // (regular FixedUpdate code)
    //....
    }

You should consideer the function as "initialized" when initCounter >= 2. Then you can operate normally.

i think this will help you: http://forum.unity3d.com/threads/86549-bug-on-order-of-activation-for-wheelcolliders?p=557907#post557907

I've just posted it. Basically you need to do to manually activate the rigidbody before usage because there seems to be a delay. If it works, please post on the thread so it gets some attention. I've submitted it as a bug already :)

This is still a bug in Unity 4 unfortunately. Now, after adding your wheel colliders, you need to do this:

gameObject.SetActive(false);
gameObject.SetActive(true);