local pitch, yaw, and roll for player controller

hey brain trust,

so i am trying to make an aerial vehicle (controlled first person using a mixture of mouse look and WASD controls)

I’m currently using the following to handle the “mouse look” aspect:

And If i try to use the “Add Roll Input” and make it execute when you hold shift and press / hold either A or D it does indeed roll the player pawn and controller…

BUT

The yaw and pitch remain global and do not rotate with the roll - which is obviously less than ideal…anyone know how i can roll the player pawn / controller and keep the yaw and pitch movements local?

FYI I’ve tried this:

And whilst it is passing 1.0 or -1.0 to the Delta Rotation X (Roll) var it doesn’t seem to actually DO anything - ie. no roll

I am going to presume we are talking about at least a semi “6-degrees of freedom flight”. If this is incorrect then some of this will need to be different:

if you are using an APlayerController, and CharacterMovementComponent then you are probably being overriden by a function “UpdateRotation()” on the APlayerController which has yet to be exposed to Blueprints.

“normally” for grounded games where UpVector=+Z the likelihood that a Pawn would need to rotate about X (roll) is very rare, so your limiter is in 2 different directions:

  • the PlayerController will often times ignore changes in roll (in 90% of cases this should never happen, so roll is “locked”)
  • the CameraManager will try to keep the Camera “right side up” as much as possible to prevent the player from becoming disoriented. again because “typically UpVector= +Z”

there are a few ways to deal with this in Blueprints:

  • drop back to pawn for the aircraft/ship because the more generic AControllers do not make the assumption of locking Roll.
    • you can swap between Character and Pawn especially within the same runtime session, it is a bit of bookkeeping to do the transition, and back again. it is far from unheard to switch Pawn classes, and Character Classes.
  • drop back to a generic AController instead of a PlayerController at least of this section.
    • if for some reason you needed what APlayerController does for this segment then the controller is a separate entity anyways,
    • the worst part the Engine might raise a fit unless you do the swap in specific order because technically it isn’t the Character, or the Pawn that is important for the Engine but a Controller object, and it is really the Controller that is tracked by the Engine hence why the easiest way to get the Player object is to use GetPlayerController(), not GetPlayer()
  • incorporate a C++ controller class that overrides the offending function, or at least temporarily takes it down a different code path.
    • you can still derive from the class, and otherwise it will behave almost identically.

if you are willing to incorporate a little C++ for this then all of this is addressable, but requires a little bit of work:
the things we need to address are: The CameraManager, and the Controller. These are actually very similar modifications that would need to happen for say arbitrary gravity.

  • the bad news: these operations are very easy and accurate in C++, because direct access to Quaternions, and the function Update UpdateRotation() is not exposed for override in Blueprints.

  • the good news: actually adding a C++ class to the project is painless, and as long as it compiles, the class can be treated like any other base class already in the Editor.

  • the C++ can be ignored for everything else, and if you decide later to use one of the other methods then even the C++ implementation can be ignored as well.

  • the Ugly news: setting up the IDE for the first time can be a chore.

if you want to continue with the C++ approach then this is a starting primer:

and then we can get back with a class for you to use.

1 Like