0
\$\begingroup\$

I have an fps rigid body script, code listed here:

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

public class Player : MonoBehaviour
{
    // Start is called before the first frame update

    [SerializeField] Camera cam;
    [SerializeField] float camSpeed;

    float yaw;
    Vector3 direction;

    Rigidbody myrigbody;
    void Start()
    {
        myrigbody = GetComponent<Rigidbody>();
    }

    // Update is called once per frame
    void Update()
    {
        cam.transform.Rotate(new Vector3(-Input.GetAxis("Mouse Y") * camSpeed, 0, 0));

        yaw = (yaw + Input.GetAxis("Mouse X") * camSpeed) % 360f;

        direction = new Vector3(Input.GetAxis("Horizontal"), myrigbody.velocity.y, Input.GetAxis("Vertical"));
    }
    private void FixedUpdate()
    {
        myrigbody.MoveRotation(Quaternion.Euler(0, yaw, 0));
        myrigbody.velocity = direction;
        

    }
}

The particular part I'm having trouble with is the last line: myrigbody.velocity = direction;This code is moving my character perfectly, except that it doesn't adjust to my rotation in game. If i rotate 90 degrees to the right in game, and press forward, I will move to the left (from the players perspective), I will move in the same direction when i press forward (or any other direction) no matter how I have rotated. How do I alter the rigid bodies velocity while taking into account how the player has rotated?

\$\endgroup\$
1
\$\begingroup\$
Vector3 worldDirection = transform.TransformVector(localDirection};

...will map a direction in an object's local space to the corresponding direction in world space, factoring in the object's rotation while ignoring its translation and scale. It's equivalent to:

Vector3 worldDirection = transform.rotation * localDirection;

or

Vector3 worldDirection = rigidbody.rotation * localDirection;

As an aside, you don't need to cache stick inputs in Update to apply them in FixedUpdate. You can just put the code that reads the analog stick values in FixedUpdate directly to simplify your code. Don't do that for instantaneous inputs like button presses/releases/taps, but it's safe for continuous inputs like analog stick deflection and button holds.

\$\endgroup\$
4
  • \$\begingroup\$ Thanks, the code works now, but I'm confused about how it works. I must be misunderstanding how your conversion is affecting the direction. How did converting it to world space fix it? I was under the misunderstanding that having a vector in world space would cause a problem like this, because world space is static and doesn't move with the player. \$\endgroup\$ – Millard Apr 22 at 16:12
  • \$\begingroup\$ btw, thanks for the tip on analog stick inputs in fixed update. \$\endgroup\$ – Millard Apr 22 at 16:14
  • \$\begingroup\$ Physics is computed in world space. So if you send it a velocity of (0, 0, 1), that means "Move in the direction of world z+" no matter which way your character is facing. By multiplying by your character's rotation, you apply the character's facing direction to that vector, translating it into a world space version that changes whenever the player's rotation changes. So if I'm rotated 90° right, then transform.rotation * (0, 0, 1) = (1, 0, 0), correctly turning my movement in the world to point along the x+ axis instead of z+. \$\endgroup\$ – DMGregory Apr 22 at 17:37
  • \$\begingroup\$ I understand it now, thanks for your help! \$\endgroup\$ – Millard Apr 22 at 17:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.