# Gameplay How do I apply direction to a velocity vector and then to the character position?

## Recommended Posts

Posted (edited)

I'm making basic fps controls. I managed to apply acceleration to a velocity vector and of course velocity to position. Everything works perfectly and the character accelerates and decelerates in 3D space. But I can't seem to figure out how to apply direction to the character. I'm trying to move the camera (character) towards the direction I'm looking at. I'm very sure the fwd, right, and up unit vectors are fine.

By the time I get to adding my velocity to the position:

  // Acceleration already calculated and it's increasing and decreasing velocity every frame.
transform.position.x += this.velocity.x * Game.Time.step;
transform.position.y += this.velocity.y * Game.Time.step;
transform.position.z += this.velocity.z * Game.Time.step;

I can't do something like this this:

  // No good.
transform.position.x += this.velocity.x * transform.forward.x * Game.Time.step;
transform.position.y += this.velocity.y * transform.forward.y * Game.Time.step;
transform.position.z += this.velocity.z * transform.forward.z * Game.Time.step;

because it won't work. I'm able to walk forward, but not to the right (nor left).

Btw, before adding acceleration to the mix, I would do something like this:

// Used to do this, but no acceleration. Only moves as soon as I press a key.
if (Game.Input.Key.upArrow.down)    Game.camera.transform.moveZ(-speed);
if (Game.Input.Key.downArrow.down)  Game.camera.transform.moveZ( speed);
if (Game.Input.Key.rightArrow.down) Game.camera.transform.moveX( speed);
if (Game.Input.Key.leftArrow.down)  Game.camera.transform.moveX(-speed);

...and the moveZ  function would look something like this:

// Move X works the same obviously, just replace forward with right.
moveZ(speed) {
this.position.x += speed * this.forward.x;
this.position.y += speed * this.forward.y;
this.position.z += speed * this.forward.z;
}

But of course this clearly doesn't accelerate the character, but my camera would move towards the direction I was looking at. I'm sure this is a very basic question with an answer I should already know

Oh by any chance you want to take a look at the acceleration function I wrote, you can see it at this pastebin. Granted, I'm sure there's way simpler ways of doing it.

Edited by Hashbrown

##### Share on other sites
Posted (edited)
1 hour ago, Hashbrown said:

I'm trying to move the camera (character) towards the direction I'm looking at.

I am assuming that transform.forward = direction camera is looking at.

I am also assuming you are using vectors for rotations and not quaternions, and rotation is normalized, and that this.velocity = acceleration.

Then moving to the right should be:

 transform.position += this.velocity * transform.right * Game.Time.step;

Edited by Scouting Ninja

##### Share on other sites
Posted (edited)
1 hour ago, Scouting Ninja said:

I am assuming that transform.forward = direction camera is looking at.

I am also assuming you are using vectors for rotations and not quaternions, and rotation is normalized, and that this.velocity = acceleration.

Then moving to the right should be:


transform.position += this.velocity * transform.right * Game.Time.step;

Hey there Ninja, thanks for the quick response. I'm using vectors instead of quaternions and rotations are definitely normalized. The forward, right and up unit vectors are working with another implementation. The problem was actually that this was never going to work for me:

// Only for moving forward and backward, doesn't work though.
transform.position.x += this.velocity.x * transform.forward.x * Game.Time.step;
transform.position.y += this.velocity.y * transform.forward.y * Game.Time.step;
transform.position.z += this.velocity.z * transform.forward.z * Game.Time.step;

I actually had to consider that I'm only using x and z in my velocity vector, and I should add the z to all xyz properties of the position vector. Same for velocity.x. I feel foolish for not noticing this, but it's working beautifully now. Visualizing everything in my head as arrows helped out too 😛 Here's the right implementation:

transform.position.x += this.velocity.z * transform.forward.x * Game.Time.step;
transform.position.y += this.velocity.z * transform.forward.y * Game.Time.step;
transform.position.z += this.velocity.z * transform.forward.z * Game.Time.step;

transform.position.x += this.velocity.x * transform.right.x * Game.Time.step;
transform.position.y += this.velocity.x * transform.right.y * Game.Time.step;
transform.position.z += this.velocity.x * transform.right.z * Game.Time.step;

Edited by Hashbrown

##### Share on other sites
Quote

How do I apply direction to a velocity vector and then to the character position?

I think the answer you are looking for is, you don't. Velocity has a direction already (providing it has magnitude), you just add the velocity to the position each (preferably FIXED) tick.

Anything to do with direction is done beforehand when you decide how to affect the velocity as a result of the player input / look direction.

##### Share on other sites

Just to expand on this, a typical simple example:

1. Player input : pressed forward
2. Apply impulse in the forward direction (determined by yaw, and atan2), with magnitude scaled to determine the player speed. Impulse is simply added to velocity.
3. Physics tick : Player position += velocity.
4. Friction : velocity *= 0.99
Things become simpler once you fix your timestep.

##### Share on other sites
6 minutes ago, lawnjelly said:

Anything to do with direction is done beforehand when you decide how to affect the velocity as a result of the player input / look direction.

So even though my controls are working, I might have it all wrong, at least intuitively I had it wrong? At the moment I have it like this:

transform.position.x += this.velocity.z * transform.forward.x * Game.Time.step;
transform.position.y += this.velocity.z * transform.forward.y * Game.Time.step;
transform.position.z += this.velocity.z * transform.forward.z * Game.Time.step;

transform.position.x += this.velocity.x * transform.right.x * Game.Time.step;
transform.position.y += this.velocity.x * transform.right.y * Game.Time.step;
transform.position.z += this.velocity.x * transform.right.z * Game.Time.step;

I should always apply direction to the position vector first, and then apply velocity to the position afterwards is what you're saying? Sorry about asking so much, just want to make sure I get it

##### Share on other sites
23 minutes ago, Hashbrown said:

So even though my controls are working, I might have it all wrong, at least intuitively I had it wrong? At the moment I have it like this:


transform.position.x += this.velocity.z * transform.forward.x * Game.Time.step;
transform.position.y += this.velocity.z * transform.forward.y * Game.Time.step;
transform.position.z += this.velocity.z * transform.forward.z * Game.Time.step;

transform.position.x += this.velocity.x * transform.right.x * Game.Time.step;
transform.position.y += this.velocity.x * transform.right.y * Game.Time.step;
transform.position.z += this.velocity.x * transform.right.z * Game.Time.step;

I should always apply direction to the position vector first, and then apply velocity to the position afterwards is what you're saying? Sorry about asking so much, just want to make sure I get it

No.  The velocity vector tells you what the direction of movement is.  If you want to turn the character to another direction, then you rotate the velocity vector.  So for example if you want to turn 30 degrees to the right, then you rotate the velocity vector by 30 degrees to the right.

After you're doing with the velocity vector, including adding any accelerations and so on, then you apply it to the position.  NewPos = OldPos + Velocity * dt

To rotate the velocity just use whatever you have... a matrix, quaternion, or whatever you use.

##### Share on other sites

Your terminology seems a bit dodgy I think. Applying direction? What does that even mean, it could mean different things in different scenarios. You can apply an impulse, or a force, to change a velocity.

You can apply an offset to change a position directly, and that is used in some games, but I am guessing you are trying to use the physics approach of having game events change objects velocities, and then the velocities in turn change the objects positions. Even in these games, sometimes you will 'teleport' an object to a position and override the velocity in some situations.

Trying to translate, you should be applying your 'player direction' (where you want them to move) as an impulse, or force, to the velocity of a 'physics object'. All of these are vector3 by the way.

In a really simple physics simulation you might have a physics object:

class PhObject
{
void Iterate()
{
// move the position each tick by the distance in each axes defined by the velocity
m_ptPosition += m_ptVelocity;

// apply some friction, so the object slows down, unless it is e.g. in space
m_ptVelocity *= 0.99f;
}

// simple functions to make the object move
void ApplyImpulse(const Vector3 &impulse) {m_ptVelocity += impulse;}
void Teleport(const Vector3 &ptPos) {m_ptPosition = ptPos; m_ptVelocity.Zero();}

// retrieve position of object (this would more likely be an interpolating function for rendering)
void GetPosition(Vector3 &ptPos) {ptPos = m_ptPosition;}

private:
Vector3 m_ptPosition;
Vector3 m_ptVelocity;
};

Providing you get this down, you want to find out how to decide what impulse to apply due to keyboard input each game tick.

void MyInputTick()
{
Vector2 move(0, 0);

if (PressingForward()) move.y += 1;
if (PressingBackward()) move.y -= 1;
if (PressingLeft()) move.x -= 1;
if (PressingRight()) move.x += 1;

float yaw = GetInputYaw(); // from mouse somehow

// rotate move vector by yaw radians (so that forward points in the look direction)
move.Rotate(yaw);

move *= PLAYER_MOVE_SPEED; // actually the impulse magnitude, but it will determine the speed

// apply the impulse to the player physics object, so that on the physics tick the player will move!
PlayerPhObject.ApplyImpulse(move);
}

Obviously this isn't debugged, it's just conceptual. It is ESSENTIAL that you read and understand the 'fix your timestep' article before doing this or you will just get more confused.

The big take home here is that the player input and the impulse is a totally separate issue to stepping the physics. Anything could need to apply an impulse or force to a physics object, not just a player pressing keys. It could be an AI monster, a motor, a missile etc etc.

##### Share on other sites
Posted (edited)
53 minutes ago, lawnjelly said:

Apply impulse in the forward direction (determined by yaw, and atan2﻿), with magnitude scaled to determine the player speed. Impulse is simply added to velocity.

12 minutes ago, 0r0d said:

NewPos = OldPos + Velocity * dt

My own way of doing this is taking the direction vector and multiplying it with the magnitude of the velocity. This was why I assumed the velocity was the result of acceleration.

So if direction = Right(1,0,0) and velocity was say 45 degrees(20,0,20) then I can use Pythagorean theorem to find the magnitude: Root((A*A)+(B*B)) So the root of 800 = 28.284 units of speed at 45 degrees.

Edit: I mean (20,0,20) = 28.284 units of speed at 45 degrees.

Then (1,0,0) * 28.284f = (28.284f ,0 ,0) moving right at the speed of 28.284 units.

Edited by Scouting Ninja

##### Share on other sites
18 minutes ago, Scouting Ninja said:

My own way of doing this is taking the direction vector and multiplying it with the magnitude of the velocity. This was why I assumed the velocity was the result of acceleration.

So if direction = Right(1,0,0) and velocity was say 45 degrees(20,0,20) then I can use Pythagorean theorem to find the magnitude: Root((A*A)+(B*B)) So the root of 800 = 28.284 units of speed at 45 degrees.

Edit: I mean (20,0,20) = 28.284 units of speed at 45 degrees.

Then (1,0,0) * 28.284f = (28.284f ,0 ,0) moving right at the speed of 28.284 units.

If I understand this right, you can do this, but at that point it is no longer in any sense 'physics', you are just moving the object position directly, there is no momentum. That kind of approach can work though and even works better in certain types of games.

## Create an account

Register a new account

1. 1
2. 2
Rutin
24
3. 3
4. 4
JoeJ
18
5. 5

• 14
• 17
• 11
• 11
• 9
• ### Forum Statistics

• Total Topics
631758
• Total Posts
3002155
×