0
\$\begingroup\$

I'm making custom car suspension(Custom wheelcollider etc), now I encountered a problem where if car gets dropped from a certain height, raycast will fail to detect collision and wheels intersect with terrain.

My raycast starts from the center of a wheel and goes down.

Example of what happens for ~1 frame when car is dropped:

enter image description here enter image description here

Then it jumps up back to normal state.

I know that Physics.Raycast detection happens every FixedUpdate, which happens rarer than Update(And I update my wheel positions in Update). But since all physics happen every FixedUpdate, doesn't it mean that rigidbodies move every fixed update too?

I don't understand where the conflict happens and why Raycast doesn't detect that ground hit for that one frame.

Wheel collider's code:

void FixedUpdate()
{

 if (Physics.Raycast(transform.position, -transform.up, out hit, springLength))
    {
        // Debug.Log(transform.name + " has hit");
        contactSpeed = (hit.distance - hitDistance) / Time.deltaTime;
        // Debug.Log(contactSpeed);
        hitDistance = Mathf.Clamp(hit.distance, maxCompression, hit.distance);
        // forceDirection = (hit.point - transform.position).normalized;
    }
    else
    {
        //resting position = springlen
        hitDistance = springLength;
    }
}

And code that modifies wheel model's transform.position:

void Update()
    {
        for (int i = 0; i < wheels.Count; i++)
        {
            UpdateWheel(i);
        }
    }

void UpdateWheel(int i)
{
    Transform wheelModel = wheelModels[i];
    PhysicsWheel wheel = wheels[i];

    Vector3 wheelPos = wheelModel.localPosition;
    //springStretch = just hitDistance's getter.
    wheelPos.y = -wheel.springStretch + wheel.radius;
    wheelModel.localPosition = wheelPos;

    Vector3 wheelRot = wheelModel.localRotation.eulerAngles;
    // wheelRot
    wheelModel.Rotate(Vector3.right * wheel.RPM * 6 * Time.deltaTime, Space.Self);

    // wheelModel.transform.localRotation = Quaternion.Euler(wheelRot);
}

Physics settings are default:

enter image description here

Clarifications:

hitDistance is used to find where raycast actually hit the ground(By subtracting radius from it, I can find out where the wheel should be), contactSpeed is delta between two hitDistances, its used to dampen the spring.

\$\endgroup\$
9
  • \$\begingroup\$ There could be numerous reasons for this behavior. I think we need to see more of your code and inspector settings. \$\endgroup\$
    – Philipp
    May 6 at 8:39
  • \$\begingroup\$ @Philipp Edited accordingly. \$\endgroup\$
    – Nick
    May 6 at 8:44
  • \$\begingroup\$ FixedUpdate runs before the physics step. So by the time you get to Update, the raycast result you've got is old news, representing the depth one physics step in the past, not the current physics state. \$\endgroup\$
    – DMGregory
    May 6 at 10:53
  • \$\begingroup\$ @DMGregory Thanks. I understood now, but I can't think of a solution except some very complex ones, which probably are bad idea. \$\endgroup\$
    – Nick
    May 6 at 12:26
  • \$\begingroup\$ Did you consider just repeating your raycast in Update to get a last-chance fix-up before the current state is rendered? \$\endgroup\$
    – DMGregory
    May 6 at 12:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.