Home > Software engineering >  Unintended player movement from transform.InverseTransformDirection
Unintended player movement from transform.InverseTransformDirection

Time:03-24

this is my first time posting on here. I'm working on a game using the new Unity multiplayer networking solution. In summary, the issue is that the player is not moving as intended.

I am trying to take player input as follows:

Vector3 worldSpaceDir = new Vector3(Input.GetAxisRaw("Vertical"), 0, Input.GetAxisRaw("Horizontal"));

then convert it to the object space coordinates of the player character:

_inputDirection = transform.InverseTransformDirection(worldSpaceDir);

The issue I'm having is with a rotation of 0 or 180 the player moves as expected with the WASD inputs, however, at 90 or 270 all the inputs are flipped(A = right, D = left, W = backward, S = forward).

I found a question that is exactly my question but no one responded with an answer. The question is quite old now so I wanted to ask it again for more visibility.

Here's a link to the original question.

CodePudding user response:

Firstly, you are taking the worldSpaceDir wrong, it should be as follow

Vector3 worldSpaceDir = new Vector3(Input.GetAxisRaw("Horizontal"), 0, Input.GetAxisRaw("Vertical"));

here we take horizontal input as X and vertical input as Z, because in Unity Forward is pointed as Z and not Y.

Secondly, we do not need to use InverseTransformDirection() we just need TransformDirection() something like following

Vector3 inputDirection = transform.TransformDirection(worldSpaceDir);

here we are telling unity to convert the worldSpaceDir that is relative to transform (local direction) into a world space direction, so we might actually give a proper name to worldSpaceDir.

The following would work for you.

private void Update() {
    Move();
}

private void Move() {
    Vector3 directionToMove = new Vector3(Input.GetAxisRaw("Horizontal"), 0, Input.GetAxisRaw("Vertical"));
    Vector3 inputDirection = transform.TransformDirection(directionToMove);
    transform.position  = inputDirection * Time.deltaTime;
}

CodePudding user response:

I think you want to go the other way round actually!

Transform.InverseTransformDirection converts a vector from world space into local space.

What you get as input however is a local vector on the XZ plane. You want to apply this direction according to your player objects orientation, if e.g. pressing right (your input is 1,0,0) the object shall move towards its transform.right vector.

So you rather want to convert in the opposite direction into world space to move the object in the Unity world space.

You should rather be using Transform.TransformDirection!

var worldMove = transform.TransformDirection(input);

Or alternatively you can also just multiply by the rotation like

var worldMove = transform.rotation * input;

Note that if you are also using a Rigidbody like the question you linked there is also Rigidbody.AddRelativeForce which basically works the same way and expects a local space vector which is then internally converted into a world space force.

  • Related