Download

Is there a way to separate camera control from FPS lag?

I have my game setup so that the player must hold right mouse button and drag the mouse to turn the camera.
During recent stress testing I noticed that when the FPS dropped below ~45 it started to have an adverse effect on camera control.
If it got below 30 FPS it got so bad that moving the mouse across the whole screen did almost nothing.

Is there a way to make it so that the player can control the camera freely regardless of how low FPS gets?
Or at the very least improve it so that they don’t lose control until a much lower FPS?

How are you moving your camera? If its based on time, it should be frame rate independent.

CameraTurnPitchRate(Rate * TempBaseRate * GetWorld()->GetDeltaSeconds());

Rate = mouse input
TempBaseRate = mouse sensitivity settings
(It directly rotates the rotation of the Pawn’s CameraBoom Component)

I tried replacing GetWorld()->GetDeltaSeconds() with a flat value but it still became unusable at low FPS.
Im not sure how Im suppose to make it frame rate independent…

What was wrong with the DeltaSeconds approach? A flat value would be unusable as that would make it frame rate dependent.

DeltaSeconds is what I had initially with the problem I described in my opening post.
I don’t know what the problem with that approach is.
I tried the flat value just to see if there would be a difference.

Verify everything is in floats and you aren’t somehow clamping to an int. Delta seconds is what you want.

They are all floats:
float Rate
float RateMod
float TempBaseRate

Does it make a difference if it is in the Pawn or the PlayerController?

Shouldn’t. You can always log the values and see whats happening.

ok.
I hobbled together a solution. Its a bit jerky but at least gives enough movement back to the camera to get it usable.
But Im not sure if it is a “good” solution or if there is a reason not to do it so:

I added this line to the camera input:
float PerformanceFactor = 1 + (FMath::Clamp(float(FApp::GetDeltaTime()), 0.01F, 0.05F) / 0.0125F);

and multiplied it after the Rate calculation:
(Rate * TempBaseRate * GetWorld()->GetDeltaSeconds()) * PerformanceFactor;

(though looking at it now I guess I could just remove GetWorld()->GetDeltaSeconds()? is DeltaSeconds different from DeltaTime?)

I decided to come back to this, to try and get rid of the jerky-ness.

Quick recap on my camera control:
Turning the camera requires holding the mouse down. This is achieved by a simple bool if/then filter in my mouse axis input function.
OnMouseDown -> bIsDown = true
OnMouseRelease -> bIsDown = false
MouseAxisInputFunction -> if (bIsDown) DoCameraMovement

After some testing I’ve discovered something odd.
If I hit ~ to bring up the console, close it, then proceed to hold the mouse down and control the camera, the camera lag goes away until I release the mouse button.

What happens when the console is opened?
If I can figure out what it is doing there it may give me a clue about how to fix my camera issues.

Maybe instead of applying the camera movement on the MouseAxisInputFunction, try applying it on tick. (you can read the axis vales without the input event)

I tried reading the Rate from MouseAxisInputFunction with an AddOnScreenDebugMessage().
Initially it displays the Rate accurately even when Im not holding the mouse button down.
Which does suggest I can apply it in the Tick().
It continues to displays the Rate accurately while I am holding the mouse button down.
However, after I release the mouse button it displays 0.0 regardless of what my mouse is doing, until I once again hold the mouse button down.

The AddOnScreenDebugMessage() is the first line of code within the MouseAxisInputFunction and is NOT subject to any kind of an if/then filter.
So it should be displaying the actual axis value, which means it would be 0.0 regardless of where I apply it.
(unless you are talking about a different method of reading the axis value?)

I no longer think the problem is with the camera control code.
I suspect there is some kind of viewport focus shenanigans going on in my UI I have to fix, but have no Idea what could be the culprit.
Thats why I asked what opening the console does, as I thought maybe if I knew it could narrow down the search.

Ive solved my issue.
Turns out it was the use of FInputModeGameAndUI for the InputMode.
I switched to FInputModeGameOnly and all camera lag is gone.

When that worked I did some checking, and Im pretty sure the issue was in how FInputModeGameAndUI’s focus is set as compared to FInputModeGameOnly.
(The former sets it to the playercontroller’s global widget variable, while the later hard sets it to the world’s GameViewport)
Interestingly the whole reason I used FInputModeGameAndUI was because I was under the impression that FInputModeGameOnly didn’t work with Widget interaction. It appears I was mistaken as I can still interact with the player’s Inventory Menus, ect. I could use FInputModeGameAndUI by manually setting the focus, but Im having a hard time seeing why I would ever need to if FInputModeGameOnly gets the job done with less work…?