Add force forward to a ball using local coordinates doesn't work as I wanted

I’m trying to control a ball for a simple game. The goal is to rotate the ball with the horizontal input on the Y axis (in world space), and then, pressing vertical input, add force to the ball to move forward or backward with the forward vector aligned to the rotation. I’ve been searching here, and I’ve found the add relative force, and also the addforce(transform.forward) to use the local axis of the ball, but, when the z axis is pointing to the floor, the ball doesn’t move anymore, since I’m applying the force against the floor. I understand that I need to use some king of combination of local and global axis, but, I have no idea on how to do it. Here’s the code I’m using:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class playerMovement : MonoBehaviour
 {
     public float force = 10000f;
     float forwardInput;
     float sideInput;
     public float turnSpeed;
     Rigidbody rb;
 
     void Start()
     {
         rb = GetComponent<Rigidbody>();
        
     }
 
     private void FixedUpdate()
     {
         GetInputs();
         Vector3 movement = new Vector3(0.0f, 0.0f, forwardInput * force * Time.deltaTime);
         transform.Rotate(Vector3.up * sideInput * turnSpeed * Time.deltaTime);
         rb.AddForce(transform.forward * forwardInput * Time.deltaTime * force);
     }
 
     void GetInputs()
     {
         forwardInput = Input.GetAxis("Vertical");
         sideInput = Input.GetAxis("Horizontal");
     }
 
 }

Also. I’m beginner so I would, if possible, really appreciate a quick explanation, Thank you so much in advance for your time.

Hello,

If you want to understand what’s happening here it’s a good idea to be able to see where you’re applying forces to your rigid body. The following code will show you where you’re about to apply the ‘forward force’.

private void FixedUpdate()
{
    GetInputs();
    Vector3 movement = new Vector3(0.0f, 0.0f, forwardInput * force * Time.deltaTime);
    transform.Rotate(Vector3.up * sideInput * turnSpeed * Time.deltaTime);
    rb.AddForce(transform.forward * forwardInput * Time.deltaTime * force);

    //lets see where we're actually going to apply force by debugging transform.forward direction...
    Debug.DrawRay(transform.position, transform.forward);
}

This will show you a debug ray (a white line) in the scene view. It will point in the direction the force is going to be applied in. It will look something like this:

146854-forward.png

Run your game and watch what happens to the debug ray when you try and move forwards. You’ll see the sphere rotates as the sphere moves forwards. As it rolls forward eventually you will be applying force into the ground and your sphere will stick there.

To make this approach work as you intend you’ll need to prevent the sphere from rotating. You can do this by using the rigid body constraints.

146859-rigid.png

This will prevent the sphere from rolling around in a realistic way. If you want more realism you’ll probably want to not constrain the rotation of the sphere and not use transform.forward as the direction in which you apply the force.

Perhaps try not rotating the ball and actually just updating an angle variable stored in your player. Use this to determine the direction you want to move the ball in. Something like:

private void FixedUpdate()
{
    GetInputs();

    //change our angle variable based on the sideInput
    angle += sideInput * sideInput * turnSpeed * Time.deltaTime;

    //calculate our direction based on the angle
    Vector3 direction = new Vector3(Mathf.Sin(angle), 0, Mathf.Cos(angle));
    direction.Normalize();

    //add the force based on the direction
    rb.AddForce(direction * forwardInput * Time.deltaTime * force);

    //debug direction
    Debug.DrawRay(transform.position, direction);
}

This will prevent the rotation of the ball from influencing the direction the force is applied in.

I hope this helps!

Best regards,

Thom.