Rolling a Sphere on one axis only

Hello, I’m trying to make a clone of an android game called “Sky Rolling Ball Run 3D”, link: https://play.google.com/store/apps/details?id=com.sa.sky.rolling.ball&hl=en.

In the game, the ball only rolls on X-axis and steers through Y-axis rotations. Z-axis is constricted so that the ball doesn’t roll in a cross pattern/uncontrollably. I have a script written in which the ball is rolling fine on the x-axis and steering on the y-axis on straight planes. But when the ball approaches a slope, it starts to rotate backward at the start of the slope, it stops rotating mid-slope and starts rotating in the correct direction at the end of the slope. This is my function to keep the ball up-right. I’m calling it in FixedUpdate() method.

private void AdjustChildRotation()
{
    float speed = rb.velocity.magnitude;

    // Only adjust the rotation when the ball is moving
    if (speed > 0.01f)
    {
        Vector3 movementDirection = rb.velocity.normalized;

        // Lock the rotation on the Y-axis only for ballDirection, to face the movement direction
        Quaternion lookRotation = Quaternion.LookRotation(movementDirection, Vector3.up);
        ballDirection.rotation = Quaternion.Euler(0, lookRotation.eulerAngles.y, 0);

        ballChild.rotation = Quaternion.Euler(0, lookRotation.eulerAngles.y, 0);

        // Calculate rolling amount based on movement speed
        float rollAmount = speed * rollMultiplier * (360f / (2 * Mathf.PI * ballChild.GetComponent<SphereCollider>().radius));

        // Apply the roll rotation only along the x-axis, allow physics to handle other axes

        ballChild.Rotate(Vector3.right, -rollAmount * Time.fixedDeltaTime * rollSmoothness);
        Debug.Log("DIrection: " + movementDirection);
    }
    //Debug.Log("Speed: " + speed);
}

I’ve searched a lot and found out that the line “ballChild.rotation = Quaternion.Euler(0, lookRotation.eulerAngles.y, 0);”, is the cause of the problem.

I commented out the line and the ball rolled correctly on the slope, granted that it wasn’t restricted to one axis only. What can I do to keep the ball rolling correctly, regardless of the terrain.

For the forward movement, I’m using “rb.AddForce(moveDirection * (forwardForce + speedIncreament) * Time.deltaTime);”, in another function.

My hierarchy: ballChild → ballParent. Rigidbody, sphere collider and the script is on parent, while the child has only the mesh.

Try using AddRelativeTorque to roll and turn the ball and freeze the Z axis on the rigidbody’s component.

Freezing an axis on the rigidbody does not work. The ball still very much spins out of control.

Do you actually want the ball itself to be a child of the rigidbody? It’s going to inherit all changes to the transform and make this more difficult than it needs to be.

Potentially instead have it as a sibling of the rigidbody, and code it to follow its position. Then you only need to rotate it to face the direction the rigidbody is travelling in, and spin it perpendicular to that direction based on the speed.

Thanks man, that did it.