Get CameraRotation/Location -> SceneCapture2D SetRotation/Location 1-frame lag

Hello,

I’ve followed and adapted the following tutorial, but I’ve run into one problem.

Where the tutorial says we need to update the Scene Capture 2D at the end of the Character Tick to avoid a 1-frame lag, doing so does not resolve the issue for my game.

The following description is more noticeable at lower framerates (such as 10fps), and is more subtle at higher framerates (such as 60fps), but is never more than a 1 frame catch-up.
I have a Scene Capture 2D in the world which is to follow the player’s camera rotation and position. If I simply get the PlayerCameraManager and get the position and rotation, using the following code, I get a ~1-frame lag where the scene in the Scene Capture 2D’s transform is updated to match the camera’s transform the following frame after the new camera angle has already been rendered to the screen.

			FVector NewLocation = ConvertLocationToActorSpace(CameraLocation, Portal, Target);
			//NewLocation.Z = NewLocation.Z - 13.f;
			SceneCapture->SetWorldLocation(NewLocation);


			//-------------------------------
			//Compute new Rotation in the space of the
			//Target location
			//-------------------------------
			FTransform CameraTransform = Controller->PlayerCameraManager->GetTransform();
			FTransform SourceTransform = Portal->GetActorTransform();
			FTransform TargetTransform = Target->GetActorTransform();

			FQuat LocalQuat = SourceTransform.GetRotation().Inverse() * CameraTransform.GetRotation();
			FQuat NewWorldQuat = TargetTransform.GetRotation() * LocalQuat;

			//Update SceneCapture rotation
			SceneCapture->SetWorldRotation(NewWorldQuat);

...
		SceneCapture->TextureTarget = PortalTexture;
		SceneCapture->CustomProjectionMatrix = Controller->GetCameraProjectionMatrix();
		SceneCapture->CaptureScene();

Just to recap, I’m calling this at the end of the player tick.

However, if I use the Controller Rotation, or a PreUpdateCamera Rotator stored on my Character (which is identical to the Controller rotation, I’ll explain why next), there’s NO lag when the camera/2D Scene Capture is rotated, only when the location changes.

I have a suspicion it partly has to do with how I handle changes to the camera’s position and rotation, so here’s a brief description:

Camera Position
I change the camera position by using the AddMovementInput function in the Character class, from the input functions in my PlayerController class.

Camera Rotation
My game is a True First Person, where the camera is locked to the character mesh’s head and follows its pitch, and the whole body/Character follows the Controller’s Yaw.
PlayerController takes axis inputs, and stores them for consumption by UpdateRotation, which I have overrided. Before I let PlayerController’s UpdateRotation consume the new rotation, I pre-update a Rotator called PreUpdateCamera in the Character class for the AnimBP to read from so that the head’s pitch animation doesn’t have any frame render lag and accurately moves, and thus the camera’s pitch does too, according to my Y-axis input.
The AnimBP’s pitch (for the Camera) and the PlayerController’s Yaw move in sync, so the camera is accurately updated.

The reason I can’t just use the PlayerController rotation for the 2D Scene Capture’s rotation, is because due to the True First Person method the camera is not 100% aligned with the ControlRotation’s Pitch. It merely gets a rotation and offsets the BlendSpace for the head based on that. So when I walk through the portal, there’s a visible 1-2 degree jump from the projected angle to my actual camera angle. I tried my best to make the lower, middle, and upper angle of the Controller and the head animation align, but even when those aligned there was still drift. No matter what, at some angle walking through the ControllerRotation-aligned-portal causes a visible jump. Also, this doesn’t solve the 1-frame delayed CameraLocation get/set. So…

Question in a nutshell:
Why is my Scene Capture 2D rotation and location only being set to the camera’s the frame after? When can I call the above UpdateSceneCapture2D code AFTER the Camera’s Pitch and Yaw have been set, and AFTER the Player Character has consumed the movement input and thusly moved the Camera’s world location, but BEFORE (or rather WHEN) the Camera visually displays this new Transform, and not on the next frame?
It’s really easy to see at 10fps with printouts of the ControlRotation, Camera’s WorldRotation, and the 2DSceneCapture’s WorldRotation that it’s literally just updating a frame behind.

Thank you to anyone who reads this all and has any ideas!

It is just the race condition (i.e it was ticking 1 frame behind).
I tried setting the Scene Capture 2D’s actor prerequisite actor to the Character that has the camera on it but it didn’t fix the issue, so:
I set the Scene Capture 2D’s actor to CanTick = true instead of ticking it from the Character, and then set its TickGroup to TG_PostUpdateWork so that the variables are updated before we actually set the rotation and location and stuff. So happy I figured that out. Posting answer here for others who run into tick race issues :slight_smile:

1 Like