How to move the CameraComponent into PlayerController

Hello,

until now I added an UCameraComponent to the character class the way it was done in the TPSTemplate or in the battery tutorial, I am not sure.
I just added a UCameraComponent to the character, and it was selected and used - I have absolutely no idea why, it was a local component variable I created.

Now I try to move the camera to an own PlayerController class, as it should be attached to the player, not to the character. (The possessed pawn can change and I don’t want every MyCharacter instance to have a camera - it is used for -s as well).
However I failed to activate it.

This is how I tried:

// MyPlayerController.h
/** Camera boom positioning the camera behind the character */
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true"))
class USpringArmComponent* CameraBoom;

/** Follow camera */
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true"))
class UCameraComponent* FollowCamera;


// MyPlayerController.cpp
AMyPlayerController::AMyPlayerController()
{
	CameraBoom = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraBoom"));

	FollowCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("FollowCamera"));
	FollowCamera->bUsePawnControlRotation = false;

}


void AMyPlayerController::BeginPlayingState()
{
	CameraBoom->AttachTo(GetControlledPawn()->GetRootComponent());
	CameraBoom->TargetArmLength = 300.0f;
	CameraBoom->bUsePawnControlRotation = true;

	FollowCamera->AttachTo(CameraBoom, USpringArmComponent::SocketName);
	FollowCamera->bUsePawnControlRotation = false;

	SetViewTarget( this );
}

If I start the game I have the same default camera I would without this extra code.
Any idea what’s wrong or how to achieve my goal?

Thanks,

Elathan

Hi Elathan,

I don’t have much experience with this particular issue myself but by the name of the function that sets the boom’s attachment (BeginPlayingState) it seems like something that is only being run once throughout the game instance. If this isn’t run again after possession has changed, the camera will stay attached to the original character.

Otherwise, can you provide the rest of your game code or your blueprints to show where these functions are being called so that I can get more context surrounding the issue?

Thanks for your answer.

Unfortunately I am sure that BeginPlayingState is called properly after the pawn is possessed. ( It is a function defined and called by PlayerController.) I use this same thing to setup functions for input binding on the same character.

MyPlayerController header:
http:///UqrPJqs9

MyPlayerController cpp:
http:///mQYR03Gr

I am not even sure if the camera defined in my PlayerController is active or not. I’ll try to find a way to find out that first.

Edit: modifying the camera defined in my PlayerController doesn’t have any effect - I think it is not used.

The Possess(…) function in PlayerController will call SetViewTarget( … ) with the possessed pawn. It was called after BeginPlayingState, so my SetViewTarget() was overwritten.

But it is still not good unfortunately - now I override the Possess function in my PlayerController, call it’s parent first, then ViewTarget(this).

The position of the camera is different now, so it is called correctly, but it still doesn’t use the CameraComponent I declared and defined in my PlayerController. There must be a way to bind the component and the controller, or?

I tried to find the answer in the source code, but without success so far.

According to the documentation:

"The CameraComponent allows you to add a camera perspective as a sub-object to an Actor. The CameraComponent will provide information about the camera’s properties if the ViewTarget is a CameraActor or an Actor that contains a CameraComponent and has its bFindCameraComponentWhenViewTarget option set to True. "

Well, bFindCameraComponentWhenViewTarget doesn’t really modify anything.

I’m not seeing any reasons as to why this wouldn’t work from the information provided. Would it be possible for you to upload the project itself? If it won’t fit on Answerhub, or you wish for it to be private, you can upload it to Dropbox or another third party hosting site and link it either here or to me on the forums in a private message. If you wish to do the private message route, my forum username is . It would be very useful to be able to tinker around with the code and the blueprints that you’re using to attempt to find the issue.

Well, the PlayerController component overwrites the function which is used by the Actor class instances to get the data from the camera component.

void APlayerController::CalcCamera(float DeltaTime, FMinimalViewInfo& OutResult)
{
	OutResult.Location = GetFocalLocation();
	OutResult.Rotation = GetControlRotation();
}

An other Actor here would search for camera component if bFindCameraComponentWhenViewTarget is set.
I suppose it’s not a bug but a feature, but… I don’t really see why can’t this work in the same way it does with other actors.

I suppose there isn’t a reasonable way to store a CameraComponenet in the PlayerController then.

It seems to me that the PlayerControllers aren’t compatible with CameraComponents - I did not expect that. I found the problem (but not a solution : ( ), see my answer below.

I can override the CalcCamera(…) in my PlayerController, and call the Actor’s implementation.
I am closer to the desired result, but something is still wrong (maybe with the cameraboom, I am just too close to the target, I suppose it doesn’t have it’s effect on it).
It was enough for me for today, I’ll try to fix this tomorrow.

I just couldn’t sleep without solving this thing :stuck_out_tongue:

I think the problem was the following: because the USpringArmComponent wasn’t the part of the actor it detected its collision, so it went close to the center, the same way it would if the owner would be too close to a wall.

I moved the USpringArmComponent to the Character class, the camera stayed in the PlayerController class.

Also, I don’t call the actor’s CalcCamera - I do the same in a more efficient way, without searching for the camera instead:

void AShPlayerController::CalcCamera(float DeltaTime, struct FMinimalViewInfo& OutResult)
{
	FollowCamera->GetCameraView(DeltaTime, OutResult);
}

I hope everything will work fine now and that this thread will be useful for others as well.

I don’t get it: Even with the following code in my custom player controller neither the camera’s location nor rotation does change:

void ATycoonPlayerController::BeginPlay()
{
	SetViewTarget(this);
}
void ATycoonPlayerController::CalcCamera(float DeltaTime, FMinimalViewInfo& OutResult)
{
	const FVector camLoc(-270.0f, 270.0f, 400.0f);
	const FRotator camRot(0.0f, -70.0f, 0.0f);

	OutResult.Location = camLoc;
	OutResult.Rotation = camRot;
	OutResult.FOV = 90.0f;
}

What am I missing?