Move character along the horizontal plane only?

Hey everyone,

Super new to development in Unity and I wasn’t able to find anything online that really answered my question - I’ve got a super simple movement script here:

// globally
public Vector2 turn;

// in Update()
horizontalInput = Input.GetAxis("Horizontal");
forwardInput = Input.GetAxis("Vertical");

rb.AddForce(transform.forward * forwardInput * speed, ForceMode.Impulse);
rb.AddForce(transform.right * horizontalInput * speed, ForceMode.Impulse);

turn.x += Input.GetAxis("Mouse X") * sensitivity;
turn.y += Input.GetAxis("Mouse Y") * sensitivity;
transform.localRotation = Quaternion.Euler(-turn.y, turn.x, 0);

And I want my character to move in the direction they are facing, but only on the horizontal plane - right now, If I l look up and press W, my player starts moving into the sky. Is there a way to somehow extract only the horizontal parts of the forward and right vectors?

Thanks!

You’re using transform.forward. This is the forward facing direction of your player, so if you look up and then move forward, you’ll move up (the direction your player is facing). You might want to use Vector3.forward instead, this is the world-space forward direction.

Well the issue is that I want to have the player move in the direction they are facing, Using Vector3.forward would make it only able to move in the world’s horizontal plane, If I am not mistaken?

Personally I have an empty gameObject, that my player script is on. and that only handles turning left/right, and moving/strafing according to that forward. Then the camera is a child of that object, so it only handles looking up/down.

You could go through all the trouble of hardcoding that yourself, or just let hierarchy do all the heavy lifting. Just remember any child object would be dealing with local space, as it’s position would technically be (0,0,0) from it’s parent. The parent object’s position would be world space.

I’m sure there’s many tutorials on a simple FPS camera/movement that can show other ways if you’re interested. :slight_smile:

then you can just set the Y component of transform.forward to zero. That will keep the player moving in the direction they’re facing, but remove all vertical motion. Like so:

Vector3 fwd = transform.forward;
fwd.y = 0;
rb.AddForce(fwd * forwardInput * speed, ForceMode.Impulse);

wideeyenow_unity’s solution would be mine as well.

Make a movement object. Usually a capsule collider with a simple script on it, much like yours but without the vertical rotation.

Then make your player a child object of the movement object. Your child object will have a script that only rotates up and down, but has no other movement. As the invisible parent object moves and turns horizontally, so will the player, but when the player looks up, the parent wont.

I’m not sure why I hadn’t thought of this! This works amazingly lol

There is also Vector3.ProjectOnPlane() which will help you pick a vector that is perpendicular to some arbitrary axis. Setting y=0 is equivalent to ProjectOnPlane with a vertical axis.