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
EDIT #2: Sorry about the Satellite names in the video, you know how testing / boilerplating is