I’ve done this myself. My game is an FPS / RTS mix where the player can take control of a lot of different pawns, often in quick succession. To avoid all those extra scene components, I create the Camera, Spring Arm and First-Person Meshes as part of the Player Controller (the latter is a pain in the ****).
To do it successfully, you need to create a custom PlayerCameraManager and override the UpdateViewTarget function. This is a direct copy-paste from my project below, you can pretty much work it out
void ABZGame_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;
ABZGame_PlayerController* BZGame_Controller = Cast<ABZGame_PlayerController>(GetOwningPlayerController());
if (BZGame_Controller != NULL)
{
UCameraComponent* ViewCam = BZGame_Controller->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 (BZGame_Controller->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);
}
}
EDIT: Also, you really want to create the controller components in the constructor.