2 UCameraComponents on actor. Pilot mode only works for the first CameraComponent

I have an actor that has:

  • 2 UCameraComponents attached to it.
  • 2 UBoxComponents attached to it.

90233-editor.png

The actor is a teleportation device. The 2 camera components registered to it are meant to be markers as to where i should move my main camera, the ■■■ components are where i am going to move my player.

I used CameraComponents rather than targets so i could use the camera viewing feature in unreal engine to get the right position set up for the camera.

The issue seems that only the first UCameraComponent can be looked through. The other cannot be previewed.

Is this a bug or am i doing something wrong:

class ECDD_API ABackdropLink : public AActor
{
	GENERATED_BODY()
	
public:	
	// Sets default values for this actor's properties
	ABackdropLink();

	// Called when the game starts or when spawned
	virtual void BeginPlay() override;
	
	// Called every frame
	virtual void Tick( float DeltaSeconds ) override;

	UPROPERTY( VisibleAnywhere, BlueprintReadWrite, Category = Backdrop )
	USceneComponent* dummyRoot;

	UPROPERTY( VisibleAnywhere, BlueprintReadWrite, Category = Backdrop )
		USceneComponent* pointA;

	UPROPERTY( VisibleAnywhere, BlueprintReadWrite, Category = Backdrop )
		UBackdropLinkCameraMarker* cameraPointA;

	UPROPERTY( VisibleAnywhere, BlueprintReadWrite, Category = Backdrop )
		UBackdropLinkTrigger* triggerPointA;

	UPROPERTY( VisibleAnywhere, BlueprintReadWrite, Category = Backdrop )
		UBackdropLinkTrigger* targetPointA;

	UPROPERTY( VisibleAnywhere, BlueprintReadWrite, Category = Backdrop )
		USceneComponent* pointB;

	UPROPERTY( VisibleAnywhere, BlueprintReadWrite, Category = Backdrop )
		UBackdropLinkCameraMarker* cameraPointB;

	UPROPERTY( VisibleAnywhere, BlueprintReadWrite, Category = Backdrop )
		UBackdropLinkTrigger* triggerPointB;

	UPROPERTY( VisibleAnywhere, BlueprintReadWrite, Category = Backdrop )
		UBackdropLinkTrigger* targetPointB;

	void IsOverlappingTarget(UBackdropLinkTrigger* target, UBoxComponent* targetPoint, UBackdropLinkCameraMarker* cameraPoint);

};

ABackdropLink::ABackdropLink()
{
	// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;

	this->dummyRoot = CreateDefaultSubobject<USceneComponent>( TEXT( "Dummy Root" ) );
	this->dummyRoot->AttachTo( this->RootComponent );

	this->pointA = CreateDefaultSubobject<USceneComponent>( TEXT( "Point A" ) );
	this->pointA->SetVisibility( true );
	this->triggerPointA = CreateDefaultSubobject<UBackdropLinkTrigger>( TEXT( "Trigger Point A" ) );
	this->targetPointA = CreateDefaultSubobject<UBackdropLinkTrigger>( TEXT( "Target Point A" ) );
	this->cameraPointA = CreateDefaultSubobject<UBackdropLinkCameraMarker>( TEXT( "Camera Point A" ) );
	this->pointA->AttachTo( this->dummyRoot );
	this->triggerPointA->AttachTo( this->pointA );
	this->targetPointA->AttachTo( this->pointA );
	this->cameraPointA->AttachTo( this->pointA );

	this->pointB = CreateDefaultSubobject<USceneComponent>( TEXT( "Point B" ) );
	this->pointB->SetVisibility( true );
	this->triggerPointB = CreateDefaultSubobject<UBackdropLinkTrigger>( TEXT( "Trigger Point B" ) );
	this->targetPointB = CreateDefaultSubobject<UBackdropLinkTrigger>( TEXT( "Target Point B" ) );
	this->cameraPointB = CreateDefaultSubobject<UBackdropLinkCameraMarker>( TEXT( "Camera Point B" ) );
	this->pointB->AttachTo( this->dummyRoot );
	this->triggerPointB->AttachTo( this->pointB );
	this->targetPointB->AttachTo( this->pointB );
	this->cameraPointB->AttachTo( this->pointB );
}

Camera system on every frame asks view target actor to give camera position by calling CameraCalc function, by default it picks first active camera component found. here you have code snipit from engine source code showing default code:

https://github.com/EpicGames/UnrealEngine/blob/c07c63dcdedb7e8ced9a81dfb864505d5db5afa3/Engine/Source/Runtime/Engine/Private/Actor.cpp#L2189

void AActor::CalcCamera(float DeltaTime, FMinimalViewInfo& OutResult)
{
	if (bFindCameraComponentWhenViewTarget)
	{
		// Look for the first active camera component and use that for the view
		TInlineComponentArray<UCameraComponent*> Cameras;
		GetComponents<UCameraComponent>(/*out*/ Cameras);

		for (UCameraComponent* CameraComponent : Cameras)
		{
			if (CameraComponent->bIsActive)
			{
				CameraComponent->GetCameraView(DeltaTime, OutResult);
				return;
			}
		}
	}

	GetActorEyesViewPoint(OutResult.Location, OutResult.Rotation);
}

So as you can see you can either activate and deactivate camera components or override CameraCalc in your actor to get position of selected camera and traser it to OutResult similarly how default code does.

And yes Camera Component are practically dummy component made to operate camera easier for blueprint only users, in C++ you don’t need to use them, you can just directly give desired camera position to OutResult, but by doing that any blueprint made (and C++ classes ofcorse) from such actor will complitly ignore camera component since you will override code that use them

Thanks! sorry for going quiet. I’m going to try and override the editor default behavior for it in this case… Thanks for the help, i’ll get back when complete!

How do i override this behaviour when editing my scene, rather than playing it? Basically this question: Event when actor selected in editor - Programming & Scripting - Unreal Engine Forums