How can I get the local velocity?

How can I get the local velocity of my pawn? I know FVector MyVector = GetVelocity(); But this is the global and not local velocity. I have a flying airplane and I would like to get the velocity on its local x-axis.

EDIT:

Answer is incomplete - I’ve left the old answer as a monument to my hastiness below.

FTransform has functions GetRelativeTransform)( and GetRelativeTransformReverse() which can be used to go from local to world and vice versa.

To get the local axes you can use the GetScaledAxis method below.

Old Answer:

I’m not sure about your terminology as local velocity does not really make sense here, so I assume you’re asking for the Global Velocity in the airplane’s orientation axes?

If so, you can use the following:

FRotationMatrix(GetActorRotation()).GetScaledAxis(EAxis::X)

You can obviously use EAxis::Y, EAxis::Z as well for left/right and up/down.

Thanks for your answer! But I’m not sure if I understand everything (sorry). Here is some of my old code which should an idea of what I’m trying to achieve:

  1. FVector VelVec = GetVelocity();
  2. float XVelocity = VelVec.X;
  3. FVector PlaneUp = GetActorUpVector();
  4. PlaneMesh->AddForce((PlaneUp)*XVelocity);

I am trying to get the planes forward speed on its own axis to turn the speed in to a slight lift. With my own old code it kind of worked. The problem was that the plane would just have to fly in the global x axis direction. So when the plane pitched straight down to get speed and new lift, it would be ignored because only the velocity in the global x axis direction was relevant.
I’m still very new to C++ so could you elaborate on your answer a bit and show me how implement the code you gave me in your answer? Thanks a lot!

Ok sure, no worries - I don’t have Unreal on this PC, so I couldn’t test this out, but I think what you’re looking for is the following:

// Get our local velocities
FVector forwardVector = GetActorForwardVector();
FVector upVector = GetActorUpVector();

// Define how much we should lift based on the local forwar speed
float liftAsPercentageOfLocaForwardSpeed = 0.15f;

// Calculate the added force in our local up direction, based on our forward speed and percentage lift
FVector addedForce = upVector.GetSafeNormal() * forwardVector.Size() * liftAsPercentageOfLocaForwardSpeed;

// Add the force
PlaneMesh->AddForce(addedForce);

Here, I assume that the forward acceleration (due to a key held down I assume) has already been applied, and you’re just adding a small lift component based on the forward speed. Is that what you’re looking for?

P.S. I haven’t used GetActorForwardVector() or GetActorUpVector() before but I assume that it gives you the vector that contains the magnitude (i.e. not normalized) and the world direction of the actor’s velocity based on its rotation. If that is not the case, you will have to replace these with functions that give this.

Also, naturally this code should only run when the forward thrust key is held down, otherwise you will get runaway upwards velocity.

First of all thanks for your answer again! Unfortunately it does not quit seem to work. I think tha problem is, that

  1. FVector forwardVector = GetActorForwardVector();
  2. FVector upVector = GetActorUpVector();
    is not actually the velocity. Its just the vector pointing up and forward from the actor I think. So what I did in my original code was just apply the force on to that vector so the plane would move in the direction of that Vector. For example GetActorUpVector is just the direction I applied the force to. What I wanted to do was apply a force to the actor up vector based on the planes speed. My Airplane has physics enabled and I do have a key that generates a forward thrust as you said. But the mechanics should be similar to a real plane so even when there is no thrust and the airplane falls straight down I should be able to stop the plane from free falling and get it into some sort of gliding behavior by pointing the nose in the direction it falls. Now GetActorVelocity did work kind of, but It ignored the current rotation of the airplane. For example the plane might be upsidedown or something, but as long as it had velocity in the global x direction a force would be applied to the ActorUpVector. But the thing is that I basically need to know the velocity form the perspective of the airplane itself. Maybe in other words: How much wind is hitting straight on the planes nose (I know that’s not what velocity is but maybe that gives an idea :D) Another example: The plane is completely horizontal and just sits in midair but falls down (because physics are enabled) when I press start/beginplay. Now ideally if I don’t press anything and leave the plane falling down nothing should happen and no force should be applied because from the planes perspective there is no velocity in the nose direction of the plane( local x-axis). I hope this makes sense and I hope my logic is not flawed :D! Again thanks for your help !

Hey just a small Update! I got it to work now. I used Unrotate Vector. I found this method after scrolling through the comments somewhere. This is what my code looks like now and it seems to do what I want.

  1. FVector V = GetVelocity();
  2. FRotator R = GetActorRotation();
  3. V = R.UnrotateVector(V);
  4. float XVel = V.X;
  5. FVector PlaneUp = GetActorUpVector();
  6. PlaneMesh->AddForce((PlaneUp)*(XVel));

I don’t know if there is a better way of doing it but this seems to work for now :). Again thank’s for your help!

3 Likes

Ah nice - glad you got it working and thanks for posting the final answer. I’m sure that will help someone out in the future.

2 Likes