Assigning a reference to a native C++ pawn/actor?

I have a player controller subclass (in C++) which my game mode it set to use by default.
From the editor, I wish to add a few pawn subclasses (also written in C++) into the scene, and assign these pawns to their own player controllers. What I’ve done is, in my player controller class, I’ve added a UPROPERTY variable which accepts a pointer to one of my pawn subclasses, effectively allowing me to use a drop-down list box to choose the corresponding pawns sitting in my scene…

The problem is, once I choose a pawn in my scene, nothing happens. The drop-down list still says “None”, and the reference is never assigned. If I drag the pawn from the World Outliner into the player controller drop-down list box, it gets a green highlight, indicating that it is compatible. But even a drag-and-drop operation doesn’t actually assign the reference!

Here’s the code from my player controller:

TPPlayerController.h:

UCLASS(Blueprintable)
class TAOOFPEG_API ATPPlayerController : public APlayerController
{
	GENERATED_BODY()
	
public:
	virtual void SetupInputComponent() override;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, DisplayName = "Card Hand", Category = "Game Properties")
	ACardHandPawn *CardHand;
};

TPPlayerController.cpp:

void ATPPlayerController::SetupInputComponent()
{
	Super::SetupInputComponent();
	EnableInput(this);
	if (!IsValid(CardHand)) {
		auto loc = FVector(-800.0f, 60.0f, 900.0f);
		auto rot = FRotator::MakeFromEuler(FVector(0.0f, 60.0f, 0.0f));
		CardHand = GWorld->SpawnActor<ACardHandPawn>(ACardHandPawn::StaticClass(), loc, rot);
		CardHand->EnableInput(this);
		InputComponent->BindAction("DrawCard", EInputEvent::IE_Pressed, CardHand, &ACardHandPawn::DrawCard);
	}
}

You might notice that I am explicitly spawning a pawn into the scene. This is just a temporary solution, for debugging purposes. What I really want to do is place these pawns in the scene with a given transform (in the editor, NOT in code), then have individual player controllers assigned to each of them. How can I do this?

PlayerController would need to be in level in order to do so, only actors on level can pick actors on level as unspawn class is not sure if actor will exist in world it is spawn on. You need to search for that actor with TActorIterator or TObjectIterator or UGameplayStatic::GetAllActorsOfClass()

But i think you code should would work anyway, but i think you should spawn pawn in BeginPlay insted of SetupInputComponent. All you need to do is create player, ither in play options or via code or blueprint with this:

This will create local player, which will cause creation of new PlayerController and as result spawn new pawn and assign it to varable… but i don’t know why you need this varable PlayerController already has pawn possesion system:

https://docs.unrealengine.com/latest/INT/API/Runtime/Engine/GameFramework/APlayerController/Possess/index.html

Using that will ensure that Pawn and PlayerController code will cooperate right and not to mention without that blueprint nodes like “Get Player Pawn” won’t work.

Speaking of which i think you can Posses and Unposses actors manually in editor toolbar, press F8 to unpossess pawn and then select other actors and clikc Possess in toolbar

In my default game mode (under project settings), I have my PlayerController set to my C++ class. So once I hit play, SetupInputComponent gets called. The problem here is that I’m supposed to use this opportunity to bind my actions to class methods, but I can’t do so without a valid reference to the classes which have the methods to call (such as the DrawCard method in ACardHandPawn class). I don’t want to spawn my pawn here, I want to drop it in the editor and have my PlayerController class pick it up from there, which would require some means of telling my PlayerController class which pawn is associated with which PlayerController class. In my CardHandPawn class, I am using the Possess method as you have described, and it works just fine… But that’s only if I spawn it first. I want to place it in the editor, NOT spawn it in code, and then tell my PlayerController to use it before SetupInputComponent gets called.

But thats impossible as i said, nonspawned class can’t associate anything on the level because in programming terms of things theres is no guarranty that this class will be placed on that level with those actors, it could be placed elsewhere without those actors, thats why you need to search for an actor with code as i mentioned.

I think better for you is set varable is something global and associated with level, and best for that is AWorldSettings. World settings is like level blueprint (you can find in Settings->World Settings), but for properties and same as level blueprint it is stored in the level, which means it can refrence to actors in it. Altering world settings is very easy, it actully simple property view of that class, so all you need is add some UPROPERTY(EditAnywhere) ;] So create class based from AWorldSettings add properties you need and change WorldSettings class in Project Settings → General Settings → World Settigns Class. Now you can read content of world settings using ()->GetWorldSettings(), ofcorse you need to cast it to your class first, make PlayerController detect that and possess selected actor insted.

Also BeginPlay should be executed before SetupInputComponent so it safe to spawn on BeginPlay. Because BeginPlay is executed right after spawn, where SetupInputComponent when player is assigned to PlayerController which happens after.

Sweet, that sounds like it would work a lot better for this situation. Thanks!
Gonna try it out now, and I’ll be back to report my success/failure

Yep, that worked! Thanks again!