- Home /
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.
$$anonymous$$ight be worth running through the Unity Roll A Ball tutorial to get your started - https://learn.unity.com/project/roll-a-ball-tutorial
Please, read the question. I'm trying to rotate the ball on the Y axis so it can rotate, not the same as in the tutorial. Thank you so much for your comment.
Please follow the tutorial. The movement is the same. You just need to adapt it to where you are looking. As I said, the tutorial will get you started, it isn't the answer. What you want to do is easy enough, the tutorial will get your part way there.
Answer by thomh_unity · Sep 30, 2019 at 10:34 AM
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:
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.
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.
Hi $$anonymous$$, thank you so much for your answer, that was exactly what I was looking for. I guess I need to refresh a lot of trigonometry and vectors from school...
About the first part of the answer, thank you so much for taking the time to explain it to me, but I was already aware of what was happening by setting the viewer to local (the axis) and selecting the ball in runtime. Then I understood that I was applying the force against the floor. But again thank you so much.
And for the solution, that was what I was looking for, a way to rotate the vector that applies the force against the ball. Again, thank you so much for your answer, really appreciated. Best regards!! Francisco.