0
\$\begingroup\$

So I have a simple script to move a character. The problem is that no matter where i'm looking at (my y rotation) it always makes me go the direction if I try to go forward, but I want it to go toward where i'm looking when I go forward or relative to where i'm looking for any direction. HOw can I do this ? (also I do not want to use a already existing fps controller) transform.forward works but only if I go forward or backward, not for left right or diagonal. (placed on player)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class player : MonoBehaviour
{
public float speed;
Rigidbody rb;

void Start()
{
    rb = gameObject.GetComponent<Rigidbody>();
}


void Update()
{
    float x = Input.GetAxis("Horizontal");
    float z = Input.GetAxis("Vertical");
    rb.velocity = new Vector3(x*speed.rb.velocity.y,z*speed);
}
}

for my camera, I am using a script I found online: (placed on player)

using System;
using UnityEngine;

public class mouseLook : MonoBehaviour
{
public enum RotationAxes { MouseXAndY = 0, MouseX = 1, MouseY = 2 }
public RotationAxes axes = RotationAxes.MouseXAndY;
public float sensitivityX = 15F;
public float sensitivityY = 15F;
public float minimumX = -360F;
public float maximumX = 360F;
public float minimumY = -60F;
public float maximumY = 60F;
Rigidbody rigidbody;
float rotationY = 0F;

void Update ()
{
    if (axes == RotationAxes.MouseXAndY)
    {
        float rotationX = transform.localEulerAngles.y + Input.GetAxis("Mouse 
X") * sensitivityX;             
        rotationY += Input.GetAxis("Mouse Y") * sensitivityY;
        rotationY = Mathf.Clamp (rotationY, minimumY, maximumY);
        transform.localEulerAngles = new Vector3(-rotationY, rotationX, 0);
    }
    else if (axes == RotationAxes.MouseX)
    {
        transform.Rotate(0, Input.GetAxis("Mouse X") * sensitivityX, 0);
    }   
    else
    {
        rotationY += Input.GetAxis("Mouse Y") * sensitivityY;
        rotationY = Mathf.Clamp (rotationY, minimumY, maximumY);
        transform.localEulerAngles = new Vector3(-rotationY, 
transform.localEulerAngles.y, 0);
    }
}

void Start ()
{
    Cursor.lockState = CursorLockMode.Locked;
    rigidbody = gameObject.GetComponent<Rigidbody>();
    if(GetComponent<Rigidbody>())
    {
        GetComponent<Rigidbody>().freezeRotation = true;
    }
}
}
\$\endgroup\$
1
  • \$\begingroup\$ Do you want your object to fly up if you look up using mouse? \$\endgroup\$
    – Nick
    Apr 22, 2020 at 5:39

3 Answers 3

1
\$\begingroup\$

You can use the object's transform to turn an arbitrary direction in local space to a direction in world space:

float x = Input.GetAxis("Horizontal"); 
float z = Input.GetAxis("Vertical");

// Some sticks/arrow keys will let both axes be 1 at once.
// ClampMagnitude ensures diagonals obey our max speed.
Vector3 localVelocity = Vector3.ClampMagnitude(new Vector3(x, 0, z), 1) * speed;

rb.velocity = transform.TransformDirection(localVelocity);

Note that, as written, this can cause the character to try to fly upward if looking to the sky. You can avoid that by instead forming a quaternion representing your "foot space" ground orientation (say, by getting the normal of the ground under you from a raycast), and rotating your local velocity by that quarternion. I show an example of something like that here.

\$\endgroup\$
2
  • \$\begingroup\$ Not sure to understand your answer.... isn't the a way to only detect my Y rotation so it doesn't matter if i'm looking up or down ? \$\endgroup\$ Mar 22, 2020 at 13:09
  • \$\begingroup\$ Yes there is. The way I showed you is one such way. If there's a particular part of the method that confused you, please describe where you got lost and we can clarify it further. \$\endgroup\$
    – DMGregory
    Mar 22, 2020 at 13:11
0
\$\begingroup\$

One suggestion is to use TransformDirection:

Vector3 v = new Vector3(x, 0, z);
rb.velocity = transform.TransformDirection(v);

Another is to use AddRelativeForce:

rb.AddRelativeForce(v, ForceMode.Acceleration);

I would prefer the second option, but keep in mind that method is adding to the velocity instead of overriding it each update.

Also, you should only use the RigidBody methods inside FixedUpdate().

\$\endgroup\$
7
  • \$\begingroup\$ The first one still makes me go in the same direction (don't fix the problem). When I try the second one, I just can't move. \$\endgroup\$ Mar 22, 2020 at 13:06
  • \$\begingroup\$ Are you using the Player's transform or the Camera's? It sounds like you need to use the Camera's transform, i.e. Camera.main.transform.TransformDirection(v); \$\endgroup\$
    – Sirius 5
    Mar 22, 2020 at 13:08
  • \$\begingroup\$ Remember to cache the result from Camera.main so that you are not calling it every frame, in Start() for example. \$\endgroup\$
    – Sirius 5
    Mar 22, 2020 at 13:09
  • \$\begingroup\$ Also, DMGregory's answer is better than mine, and he beat me by 2 minutes, lol \$\endgroup\$
    – Sirius 5
    Mar 22, 2020 at 13:10
  • \$\begingroup\$ @Samuel It sounds like you may have forgotten to rotate your player character to match the camera's facing direction. Try looking at your character in the scene view when playing the game — as you turn your camera, does it start to look out the side/back of your character's head, instead of the front? \$\endgroup\$
    – DMGregory
    Mar 22, 2020 at 13:11
0
\$\begingroup\$

Just use transform., you get a vector that is pointing relative to the object.

If you don't want object to fly up when its transform is looking into the sky, do this:

    float x = Input.GetAxis("Horizontal");
    float z = Input.GetAxis("Vertical");

    Vector3 forward = transform.forward; 
    //here, make Y component of the vector 0, thus only using it for direction on the flat plane.
    forward.y = 0;

    rb.velocity = forward * speed * z + transform.right * speed * x;
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .