x

Search in
Sort by:

Question Status:

Search help

  • Simple searches use one or more words. Separate the words with spaces (cat dog) to search cat,dog or both. Separate the words with plus signs (cat +dog) to search for items that may contain cat but must contain dog.
  • You can further refine your search on the search results page, where you can search by keywords, author, topic. These can be combined with each other. Examples
    • cat dog --matches anything with cat,dog or both
    • cat +dog --searches for cat +dog where dog is a mandatory term
    • cat -dog -- searches for cat excluding any result containing dog
    • [cats] —will restrict your search to results with topic named "cats"
    • [cats] [dogs] —will restrict your search to results with both topics, "cats", and "dogs"

Small Rotation Changes Being Ignored (Precision Error?)

I am working with a camera with very small FOV values to simulate scoped shots.

I have implemented a system to simulate aim sway that comes from the player's breathing, where the aim of the player will move around a bit over time when scoped, based on some curves that add to the controller's pitch and yaw every frame.

This is an example of what I use for the yaw part of this process (pitch is identical):

 float elapsed = GetWorld()->GetTimeSeconds() - ScopedInStartTime;
 if(YawCurve)
 {
       float minTime = 0.0f;
       float maxTime = 0.0f;
 
       YawCurve->GetTimeRange(minTime, maxTime);
 
       float sampleTime = FMath::Fmod(elapsed, maxTime - minTime);
       float sampledYaw = YawCurve->GetFloatValue(sampleTime);
 
       float yawToAdd = sampledYaw - LastYawVal;
 
       LastYawVal= sampledYaw;
       controller->AddControllerYawInput(yawToAdd);
 }

This works well when we are adding relatively large* angles each frame (in the range of 0.01f). However, as soon as the curve's gradient approaches zero, there is a range of very small values for yawToAdd that just seem to stop adding to the rotation, so slow interpolation of small values breaks and the movement is abruptly stopped.

At first I thought it might be floating point imprecision, as at those points we are adding a number that is usually in the hundreds (-180.0f to 180.0f), with one that is sometimes as small as 0.0005f. However, when inspecting and debugging around the function where the RotationInput rotator is added (APlayerCameraManager::ProcessViewRotation), I can verify that even those small values get added correctly, so I should still see the camera movement at those moments, but no change is apparent in the game.

Am I missing something here? is there a better way to add small rotations? Does the camera do some sort of check before updating its matrices and small deltas are ignored? Any help would be greatly appreciated

* I am using a 14x zoom factor to test, so even those deltas for aim rotation matter, as the breaks are very apparent, 0.01f each frame means around 3cm of movement every frame if we are looking at something that is 170m away.

Product Version: UE 4.20
Tags:
more ▼

asked Apr 15 '19 at 12:06 PM in C++ Programming

avatar image

B0RoN
8 1 3

(comments are locked)
10|2000 characters needed characters left
Viewable by all users

1 answer: sort voted first

If you follow AddYawControllerViewInput you'll come to Controller.cpp which contains:

 void AController::SetControlRotation(const FRotator& NewRotation)
 {
 #if ENABLE_NAN_DIAGNOSTIC
     if (NewRotation.ContainsNaN())
     {
         logOrEnsureNanError(TEXT("AController::SetControlRotation about to apply NaN-containing rotation! (%s)"), *NewRotation.ToString());
         return;
     }
 #endif
     if (!ControlRotation.Equals(NewRotation, 1e-3f))
     {
         ControlRotation = NewRotation;
 
         if (RootComponent && RootComponent->bAbsoluteRotation)
         {
             RootComponent->SetWorldRotation(GetControlRotation());
         }
     }
     else
     {
         //UE_LOG(LogPlayerController, Log, TEXT("Skipping SetControlRotation for %s (Pawn %s)"), *GetNameSafe(this), *GetNameSafe(GetPawn()));
     }
 }

Here you can see that a check is performed agains the current rotation (ControlRotation) and the new desired rotation (NewRotation). The check is to see if the rotations are equal within a tollerance of 1e-3f and if they are, then the new rotation is discarded. Are your rotation changes small enough to get discarded at this point?

If the above is the problem then the fix is pretty straight forward. AController::SetControlRotation is virtual, so you'll need a custom controller class (if you don't already have one) and simply override this equality tollerance check. You could of course modify the engine source directly, but I woudn't in this case.

I'd also track your game state so your new custom code is only called when you're in sniping mode, otherwise it falls back to the existing SetControlRotation which has this tollerance check to avoid twitchy movement.

more ▼

answered Apr 15 '19 at 02:32 PM

avatar image

phil_me_up
1.5k 6 6 12

avatar image B0RoN Apr 15 '19 at 02:39 PM

I'll try and get back to you, but that seems promising. (it's Jaime, (formerly) from PT btw, such an amazing coincidence! :D )

avatar image phil_me_up Apr 15 '19 at 03:00 PM

Ha, small world! I thought the username looked familiar but didn't make the connection. Hope that works out for you and you're enjoying whatever you're working on now :)

avatar image B0RoN Apr 15 '19 at 03:10 PM

That worked amazingly well, thank you very much!

(comments are locked)
10|2000 characters needed characters left
Viewable by all users
Your answer
toggle preview:

Up to 5 attachments (including images) can be used with a maximum of 5.2 MB each and 5.2 MB total.

Follow this question

Once you sign in you will be able to subscribe for any updates here

Answers to this question