Camera has Invalid Transform after re-attaching specific number of times. Black Screen!

UPDATE POST

I’m having possibly the strangest issue re-attaching my Camera / Spring Arm to different actors and can’t pin it down. I’ve posted on Answerhub Here: Camera Transform Breaks after Re-Attaching Specific # Of Times. - Cinematics & Media - Epic Developer Community Forums

I’ve added a more detailed explanation below, and here’s the video (vid is unlisted):

I have customized Player Camera Manager to use the Camera on the Player Controller instead of a Pawn or Actor. This is because I want the Camera to switch to different Actors as and when I want, and I don’t want to have the overhead of loads of cameras on every pawn or object, each with it’s own settings etc. This was a relatively simple change, and here’s my new code in PlayerCameraMananger:



void AGESGame_CameraManager::UpdateViewTarget(FTViewTarget& OutVT, float DeltaTime)
{
	if ((PendingViewTarget.Target != NULL) && BlendParams.bLockOutgoing && OutVT.Equal(ViewTarget))
	{
		return;
	}

	FMinimalViewInfo OrigPOV = OutVT.POV;
	OutVT.POV.FOV = DefaultFOV;
	OutVT.POV.OrthoWidth = DefaultOrthoWidth;
	OutVT.POV.bConstrainAspectRatio = false;
	OutVT.POV.ProjectionMode = this->bIsOrthographic ? ECameraProjectionMode::Orthographic : ECameraProjectionMode::Perspective;
	OutVT.POV.PostProcessBlendWeight = 1.0f;
	bool bDoNotApplyModifiers = false;

	AGESGame_PlayerController* OwnerPC = Cast<AGESGame_PlayerController>(GetOwningPlayerController());
	if (OwnerPC != NULL)
	{
		UCameraComponent* ViewCam = OwnerPC->GetViewCamera();
		OutVT.POV.Location = ViewCam->GetComponentLocation();
		OutVT.POV.Rotation = ViewCam->GetComponentRotation();
		OutVT.POV.FOV = ViewCam->FieldOfView;
		OutVT.POV.AspectRatio = ViewCam->AspectRatio;
		OutVT.POV.bConstrainAspectRatio = ViewCam->bConstrainAspectRatio;
		OutVT.POV.ProjectionMode = ViewCam->ProjectionMode;
		OutVT.POV.OrthoWidth = ViewCam->OrthoWidth;
		OutVT.POV.PostProcessBlendWeight = ViewCam->PostProcessBlendWeight;

		if (OwnerPC->GetViewCamera()->PostProcessBlendWeight > 0.0f)
		{
			OutVT.POV.PostProcessSettings = ViewCam->PostProcessSettings;
		}

		if (!bDoNotApplyModifiers || this->bAlwaysApplyModifiers)
		{
			ApplyCameraModifiers(DeltaTime, OutVT.POV);
		}

		SetActorLocationAndRotation(OutVT.POV.Location, OutVT.POV.Rotation, false);
		UpdateCameraLensEffects(OutVT);
	}
	else
	{
		Super::UpdateViewTarget(OutVT, DeltaTime);
	}
}


As you can see, all it does is grab the data from the Controllers object ‘View Camera’.

Alongside this, My PlayerController has the ability to change 'view’s on the Camera, but always starts in ‘Default’ view. It’s relatively simple, whenever the player changes view or calls ‘SwitchSatellite’, it sets CurrControlledSatellite to the new Satellite and attaches the camera to it. I attach the camera because that way I don’t have to manually tick it’s position to just equal that of the Satellite. This is probably the way it should be done, but perhaps I’m wrong?



void AGESGame_PlayerController::UpdateView()
{
	if (CurrControlledSatellite.IsValid())
	{
		switch (CurrentViewType)
		{
			case EGESViewType::VT_Default:
				CanMoveView = true;
				CameraSpringArm->TargetArmLength = DefaultArmLength;
				GetTransformComponent()->AttachTo(CurrControlledSatellite->GetSatelliteMesh(), TEXT("b_Root"), EAttachLocation::SnapToTarget, true);
				GetCameraSpringArm()->bAbsoluteRotation = true;
				GetCameraSpringArm()->SetRelativeLocationAndRotation(FVector::ZeroVector, FRotator(-30.f, 150.f, 0.f));
				GetDustParticle()->AttachTo(CurrControlledSatellite->GetRootComponent());
				break;
			case EGESViewType::VT_Laser:
				CanMoveView = false;
				CameraSpringArm->TargetArmLength = 0.f;
				GetTransformComponent()->AttachTo(CurrControlledSatellite->GetSatelliteMesh(), TEXT("LaserSocket"), EAttachLocation::SnapToTarget, true);
				GetCameraSpringArm()->bAbsoluteRotation = false;
				GetCameraSpringArm()->SetRelativeLocationAndRotation(FVector::ZeroVector, FRotator::ZeroRotator);
				GetDustParticle()->AttachTo(CurrControlledSatellite->GetRootComponent());
				break;
			case EGESViewType::VT_Overview:
				CanMoveView = true;
				CameraSpringArm->TargetArmLength = OverviewArmLength;
				GetCameraSpringArm()->DetachFromParent(false);
				GetCameraSpringArm()->bAbsoluteRotation = true;
				GetCameraSpringArm()->SetWorldLocationAndRotation(FVector(0.0f, 0.0f, 0.0f), FRotator(0.0f, 0.0f, 0.0f));
				GetDustParticle()->AttachTo(CurrControlledSatellite->GetRootComponent());
				break;
			default:
				break;
		}

		ViewCamera->FieldOfView = 90.0f;
	}
	else
	{
		CanMoveView = true;
		CameraSpringArm->TargetArmLength = OverviewArmLength;
		GetTransformComponent()->DetachFromParent(false);
		GetCameraSpringArm()->bAbsoluteRotation = true;
		GetTransformComponent()->SetWorldLocationAndRotation(FVector(0.0f, 0.0f, 0.0f), FRotator(0.0f, 0.0f, 0.0f));
		GetDustParticle()->AttachTo(GetTransformComponent());
	}
}


Now, Originally the Satellites’ were Pawns - and I simply possessed the different Satellites instead, but really it makes no difference. The Possession was never a problem, it’s the attaching of the camera. Whenever I do this EXACTLY fifteen times - the Camera looks as if it’s further away from the Satellite. When I debug however, all the information about it’s relative location, world location, attachment, target arm length and FOV are IDENTICAL. There doesn’t seem to be any change to that whatsoever, and yet the view changes dramatically.

The issue also doesn’t seem to be related to Spawning. In the video, the ‘Launch Satellite’ button spawns a new actor and attaches to it. The list on the right hand side allows me to switch between all my spawned satellites. Whenver I do ANY of these things exactly 15 times, the view changes. If I carry on doing it some more, the whole screen goes black, as if the camera has been places outside the World Bounds or something. It’s incredibly werid… since the details panel shows a regular transform.

This has led me to believe that there is a conflict in PlayerCameraManager perhaps when it comes to getting the view target? It must fail at some point, and therefore just renders the screen black.

EDIT: The reason I posted this in the ‘Feedback’ section is because I feel as though there may be an underlying issue in PCM, if that’s not correct let me know and I’ll move it :slight_smile:

EDIT #2: Sorry about the Satellite names in the video, you know how testing / boilerplating is :stuck_out_tongue:

>EDIT: The reason I posted this in the ‘Feedback’ section is because I feel as though there may be an underlying issue in PCM, if that’s not correct let me know and I’ll move it
sounds like something which should be confirmed on answerhub :wink:

Probably true but I usually get a faster / more detailed response here instead of the 'hub :wink:

Hate to do this but… baconbump.

Moved to 4.9 recently and this is still occurring, and I still can’t track it down. Everything attaches like it’s supposed to so it seems, but the camera just doesn’t want to play ball - still behaves exactly as above.

Also, the Actors aren’t dynamically spawned anymore. They’re spawned at the start of the game as part of a loop and added to a ‘Pool’ which merely activates and deactivates them when they are ‘spawned’ by the player. The issue doesn’t seem to be related to Spawning either it seems.

Bump. Still not had a fix for this mentioned anywhere.

I’ve been debugging more and more information, and I’ve found that there is literally no difference in the Camera’s relative location or any scaling changes in the Satellite when this happens. I have however discovered that when the screen goes black, it’s because the Camera Transform is possibly invalid. You can see in this video that the camera has a World-Space Location of #INDF00 - AKA an infinite undefined float and something has gone massively wrong somewhere. This HAS to be an Engine bug…

Watch this in Full-Screen to view the debugging information. I still haven’t figured out why the camera seems to ‘move’ when 15 Satellites are spawned or when it changes view 15 times… there is literally NO difference in it’s information.

Debug Key:

  • Satellite Mesh Scale
  • Satellite Root Component Scale
  • Satellite Actor Scale
  • Camera WS Location, Spring Arm WS Location
  • Camera Relative Location, Spring Arm Relative Location
  • Camera FOV
  • Target Arm Length
  • View Camera RootAttachmentActor(), View Camera AttachParent Name, Spring Arm Attach Parent Name.

And more weirdness discovered… The Spring Arm Socket Location now has an Invalid Relative Location…

Traced the issue back further to UpdateDesiredArmLocation in USpringArmComponent.cpp, near the bottom of the function where it tries to get the RelativeSocketLocation.



	// Form a transform for new world transform for camera
	FTransform WorldCamTM(DesiredRot, ResultLoc);
	// Convert to relative to component
	FTransform RelCamTM = WorldCamTM.GetRelativeTransform(ComponentToWorld);

	// Update socket location/rotation
	RelativeSocketLocation = RelCamTM.GetLocation();
	RelativeSocketRotation = RelCamTM.GetRotation();


When I hover over ComponentToWorld, the ‘Scale’ is set as #INDF00. I guess this means it can’t derive the Relative Transform properly and that in turn is why I end up with an Invalid Location. Why would ComponentToWorld have an invalid Scale?

EDIT: Fixed it! I told both the Spring Arm and the View Camera to use AbsoluteScale instead of whatever they were using before. I guess it was somehow being corrupted when attaching to different objects. I’ve fixed it now by using Absolute Scale, but the question is why is the Scale being corrupted or not correctly derived in the first place…