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

Hey @aerospike_andy how are you doing?

I’ve been trying to find a way to do it onlye with Enhanced Input and Bluepirnts and I found that you can use something like this BP:


This is how it looks in game:

Of course, you can modify it to make it much smoother, but this is the most basic way to do it.

Hope this helps you!

2 Likes

this is amazing! thank you!

1 Like

Hi BRGJuan,

Sorry this didn’t work, seems i can’t apply local rotation for some reason - what object / class did you do this in? I am in the PlayerController class…

1 Like

Hello again @aerospike_andy how are you?

I’m sorry it didn’t work! Let me be more specific:

To be able to apply local rotation, you need to implement those inputs to a Pawn instead of you Player Controller. As you are applying it to an actor, not to the controller itself.

Let me show my complete setup:

  1. I created a Pawn with these components:

  2. Added this on Begin Play to initialize the subsystem:

  3. Implemented the previously shared inputs.

That should allow you to keep working from that point!

Let me know if you need more info or help!

That’s great! Will give it a go this evening!

Does this suffer from gimble lock? Or can it barrel roll forever?

You can do barrel rolls until you get motion sickness if you want hahaha

It’s completely free movement!

sweet! got that working!

but it broke the “movement”:

unsure why this no longer works…

tried this:

and this does return what appear to be plausible values - but the add movement input call on the player pawn doesn’t do anything…

Ok so this KINDA works:

using either the local transform or world transform - but i can’t for the life of me work out what i should pass to it to get it to move right / left / up / down / forward / back

it seems kinda random

OK so i’ve solved this - and here’s the full solution if anyone needs to do something similar - All of this is on a “default pawn” class actor:

1 Like