Download

Need some help with axis to rotator logic

Hi! I’m trying to get a bit more control of my input and how it relates to my character’s movement.
But rotators and conversion math between rotation, floats, direction, vectors, etc isn’t my strong suit.

Currently, my character’s movement is simply:
W = +1 to XAxis
S = -1 to XAxis
A = +1 to YAxis
D = -1 to YAxis

Those inputs are fed to MovementInput like this.



FRotator Rotation = Controller->GetControlRotation();
if (GetCharacterMovement()->IsMovingOnGround() || GetCharacterMovement()->IsFalling())
{
  Rotation.Pitch = 0.0f;
}

const FVector Direction = FRotationMatrix(Rotation).GetScaledAxis(EAxis::X);
AddMovementInput(Direction, XValue);

What I want is instead of treating X axis and Y axis separately. I wish to have the direction fed and influenced by both and interpolate towards the target direction set by the player. (which is only 8 directions)

So if the player is facing forwards, and presses S, I wish to have the direction interpolate from forwards to back along 180 yaw axis (rotation wise that is, I understand this would involve both X and Y when doing a direction?) Currently it only goes from +1x to -1x and ignores Y, how do I emulate/translate it into a rotation?
Axis.jpg](filedata/fetch?id=1803188&d=1597874778)

I can do the lerping part just fine, but I’m not sure how I would translate the X and Y axis into a combined direction?

TDLR: I have have the controller rotation.
I have an XAxis in float, and a YAxis in float which represents player input.
I wish to use these variables to interpolate a desired direction I can input into AddMovementInput(FVector Direction, float Scale)

The differences between forward vectors, rotation, local to world space etc and how to make use of them correctly are currently a bit hard for me to wrap my head around.

I am not sure I understand what you are trying to do. You have the code you posted bound to your forward key (in X direction)? And the same for your right key in Y direction? And instead of calling AddMovementInput separately for both you want them combined and just call AddMovementInput once with both inputs already factored in into the Direction variable?

If that is what you are trying to do you would basically just add the world directions maybe like so



FVector CombinedDirection = FRotationMatrix(Rotation).GetScaledAxis(EAxis::X) * XValue + FRotationMatrix(Rotation).GetScaledAxis(EAxis::Y) * YValue;
AddMovementInput(CombinedDirection, 1.f);


However, all you would be doing then is what AddMovementInput would do anyway for you a few function calls down the line. I also don’t understand what you are lerping. If you mean that you don’t want X or Y to jump immediately from 1 to -1 you would lerp XValue and YValue beforehand and then do the above calculation with the lerped values.

Correct! Thank you so much for this information, I’ve been asking around and looking for this information for a while, I did suspect Frotationmatrix was what I was looking for, but I don’t have that much experience with 3d space related programming.

I wish to do this so that the character is moving forward in the same direction it is rotating (interpolating from the current direction to the input direction), making it run around in a circle to turn around. (While also playing the appropriate animations along the way) It may seem odd and arbitrary at first glance, but it looks more weighted and feels much, much better with the style of animations I’m using.

I can throw up a comparison video if you are curious.

Edit: Well, **** you’re right. Turns out directions work differently than I expected, all lerping does is slow the movement speed in that direction down, not the rotational direction the character faces. I want to handle the rotation of the direction, not the magnitude.


FVector DesiredDirection = FRotationMatrix(Rotation).GetScaledAxis(EAxis::X) * XAxis + FRotationMatrix(Rotation).GetScaledAxis(EAxis::Y) * StrafeValue;
FVector CombinedDirection = FMath::VInterpConstantTo(CombinedDirection, DesiredDirection, DeltaTime, 6);
AddMovementInput(CombinedDirection, 1.f);

I thought it would be more like a rotation, I was expecting it to be like the character is rotated to face one direction, then by slowing it down it would run and turn slower to another direction. Instead it just runs slower, but still in the same direction. Now I’m not sure how to approach this at all.
Perhaps I need to create my own version of the AddMovementInput function?

Someone elsewhere suggested the “Atan2” function, perhaps I should look into that.

Edit2: Your suggestion to interpolate the inputs first sort of gets me halfway there. But I’m trying to interpolate the direction the character runs towards, not the speed it moves at and I want to directional controls to work in a circle, rather than a linear X + Y direction. (So that if the player turns 180 degrees, it will also run forwards, diagonal forwards, sideways, diagonal backwards, then back, in a smooth turning motion) Hence why I tried to do it with the direction instead.

I guess what I am looking for then is a way to get the X and Y direction by using a rotator instead of getting them directly from the input, and instead use the input to calculate the rotation?

I get the impression that you misinterpret what AddMovementInput does or rather is supposed to do. The function is just there to tell you what controller’s input is or at a higher level, “What button on the keyboard did the user press?”. The way you calculate that input it is relative to the view but you could also just take e.g. XValue directly to get the absolute direction. In any case these values are not really meant to be interpolated or fiddled with too much. What you want to do would traditionally be handled within a physics function for the movement. You could take a look into the character movement component into the function CalcVelocity to get a basic idea of how to use an input vector (I think they call it Acceleration there). Giving something “weight” requires you to do approriate physics calculations which is usually done by calculating a velocity for the object (taking external forces and input acceleration into account). It is not as simple as just interpolating between a few input values.

Yeah, I started here because I was thinking I could translate the player x/y input into a circular rotation. Seems like AddMovementInput just doesn’t work like I was hoping.

Oh, I am not looking to implement actual physics (unless that turns out to actually be easier), but rather simulate weight and acceleration simply by interpolating the character’s moving direction a bit.

But I’ll see if I can make some more sense of the Character Movement component, but I struggled to get a good sense of how the input is being used in the end. But I’ll keep looking.

Edit: I have an idea! Currently it seems like movement direction is purely based on input and the character just rotates towards that direction indendently.
Is it possible to make the movement take the character’s rotation into account, so that while the character rotates, it also moves in that direction, instead of being purely based on input direction and camera, and ignoring the character.