Here’s some context: I’m trying to make a simple 3D platformer game as a rite of passage into Unity and C# development. I can move around my sphere using WASD and AddForce, and there was no issue with that because my camera position was fixed, and so was the relation. I followed a tutorial to get an orbital camera that can be controlled via the mouse, and that worked out nicely.
I soon realized that now that I have an orbital camera, ‘W’ doesn’t mean forward anymore - direction is locked on an axis. This is where things start to get a bit muddy for me, I tried to use some math to get the direction the camera is facing and use AddForce in relation to the camera direction (I probably did that math wrong).
After I tried doing that for about 2 hours, I thought I’d try to scour through google one more time, then I found AddRelativeForce - for a moment, I really thought that was going to be the answer, so I implemented it. Very soon after that, I realized, “Oh, wait a minute… my player rolls around, so local z and x aren’t always flat, oops.” And that’s where I am now:
I don’t understand what math to use, and I can’t find any tutorials, and nobody else seems to have asked, at least not that I can find. Here’s my code with the (most likely incorrect) math technique, the issue I’m having is in the FixedUpdate function, between lines 79 and 94:
using UnityEngine;
public class PlayerController : MonoBehaviour {
public GameObject playerCam;
public float forwardForce = 50f;
public float speed = 5f;
public float jumpHeight = 6f;
private Rigidbody rb;
private bool up;
private bool down;
private bool left;
private bool right;
private bool jump;
private bool brake;
// Use this for initialization
void Start() {
rb = GetComponent<Rigidbody>();
}
// Update is called once per frame
void Update()
{
if (Input.GetKey("d"))
{
right = true;
}
else
{
right = false;
}
if (Input.GetKey("a"))
{
left = true;
}
else
{
left = false;
}
if (Input.GetKey("w"))
{
up = true;
}
else
{
up = false;
}
if (Input.GetKey("s"))
{
down = true;
}
else
{
down = false;
}
if (Input.GetKey("space"))
{
jump = true;
}
else
{
jump = false;
}
if (Input.GetKey("x"))
{
brake = true;
}
else
{
brake = false;
}
}
void FixedUpdate() {
var heading = transform.position - playerCam.transform.position;
var distance = heading.magnitude;
var direction = heading / distance; // grabbed this example off of the unity reference
if (left){
rb.AddForce(new Vector3(-1 * speed * Time.deltaTime, 0, 0).magnitude * direction, ForceMode.VelocityChange);
}
if (right){
rb.AddForce(new Vector3(1 * speed * Time.deltaTime, 0, 0).magnitude * direction, ForceMode.VelocityChange);
}
if (up){
rb.AddForce(new Vector3(0, 0, -1 * speed * Time.deltaTime).magnitude * direction, ForceMode.VelocityChange);
}
if (down){
rb.AddForce(new Vector3(0, 0, 1 * speed * Time.deltaTime).magnitude * -direction, ForceMode.VelocityChange);
}
if (jump)
{
if (rb.velocity.y < .01 && rb.velocity.y > -.01) // I know that this method allows for a potential jump mid-peak, going to rewrite later
{
rb.AddForce(0, 1 * jumpHeight, 0, ForceMode.Impulse);
}
}
if (brake)
{
rb.AddForce(-rb.velocity / 18, ForceMode.Impulse); // This slows down the sphere in all axes, going to replace this later
}
}
}