How to calculate actor Roll from two Input Axes?

Hey everyone, I have a problem that I’ve been trying to solve for 4 days now and I can’t find any help on this specific problem, so I came to the forums for help!

I’m trying to make a 2D movement control for a player actor. The character is in a 3D space, but is restrained to move on a 2D plane. Basically its a sideview game with a swimming fish that the player controls, who can swim up, down, left right. I’m trying to make the fish face the direction of the movement, but I just cannot figure out how to calculate the rotation.

My setup:

  • A controlled actor that moves on
    YZ plane in the world (custom actor from scratch, not a preset inherited pawn with Player Movement!)
  • In Input settings, I made 2 input axes: Right axis controlled by D and A, and Up axis is controlled by W and S (basic WASD movement)
  • I’m using a timeline to Lerp from current Roll to a target Roll (to give a quick smooth turn instead of snapping to face the new direction). When input changes (the character changes direction), timeline replays, lerping from the current rotation to the target one
  • With how my components are set up, and how the actor is oriented in the world space, I need to rotate the mesh along X (Roll) in a 360 degree range
  • Attached screenshots of the setup in question

My question (marked on the 2nd screenshot): How can I calculate a Roll value from the WASD inputs? So if I press W and D (going up-right diagonally), it should return 45° Roll. If I go straight down it should return 180° and so on. I figured I can use a Make Rotator from [something] or Make Rotation from Axes or such, but they require multiple Vector input nodes and I don’t know where to plug what, and how that would work.

What didn’t work:
I have made many many attempts previously, with trying to multiply Input values by 90, subtract from 180 if I’m also moving down, a ton of branches and variables, but it was a huge mess, and it wouldn’t work properly. Most of the time there was a random spin, if I went over 180 (so 178, 179, 180 then jumped into negative -179). With certain methods it went properly into 181, 182 etc. but it would do a crazy 360 spin around to “continue” the rotation from the other way around.

In other methods, it did the spin seemingly randomly, say going from 220 to 221 degrees, even though it didn’t go into negative values.

If anyone has an answer on how to get this “target rotation”, please let me know, I’ve been going insane over trying to get this to work, and I’m convinced that I’m just unaware of a simple method that can do this! Thank you so much in advance!

Me again, I managed to solve the issue eventually and I came back to upload the answer in case anyone else might run into the same problem/wants to do the same thing.

The solution:

  • First step was making a vector and
    plugging my Right and Up axis input into X
    and Y of the vector respectively.
  • Next I plugged the newly created vector into a ‘Make Rot from Y’ node, then used right click → Split Struct Pin on the output pin of Make Rot from Y, splitting it into a Roll-Pitch-Yaw output.
  • Lastly I connected only the Roll value to my player model’s Roll (in my case, into the Lerp node instead). Without splitting the rotator pin, and wiring it straight into my character, it rotated it in another axis at the same time, which was unwanted, so hence I used Roll only.
  • Uploaded screenshot, highlighted the solution part (rest of blueprint remained unchanged)

In addition to handling 2-axis input correctly, this method (using rotator) also eliminated the random spin around the other way when passing into negative degrees, as I believe rotator variable types can handle this internally!

I hope this will be able to help someone in the future, in case someone finds this post. I believe this will work if your character moves on another plane (let’s say top down view, moving in world XY) by changing the pin connections around. Have fun makin’ games guys! :slight_smile:

2 Likes

This is exactly what I needed, thank you!