How Atank can is related to TankPlayerController

How return Cast<ATank>(GetPawn()); works ?

Seem like its return a pawn information as in ATank instance (pawn type),
but how from TankPlayerController it know that the connected pawn is actually the Tank->tankBP.

the only place i can see there relation,is in the TankGameModeBP.

Please correct my logic if made mistakes in the question itself.

The TankPlayerController doesn’t actually know that it’s Pawn is an ATank. Cast<ATank>(GetPawn()) is you explicitly telling the TankPlayerController that it’s Pawn is an ATank.

This works because, as you point out, we set the Default Pawn Class to Tank_BP in TankGameModeBP. If we didn’t do that, the Cast would fail and the TankPlayerController wouldn’t work.

1 Like

Thanks mate,
I think I dont understand how Cast work then, and how its connected with the TankGameModeBP.
how come it knows to find the pawn…

In this scenario, the connection with TankGameModeBP is that this is where we tell unreal what to use for our Default Pawn Class and Player Controller Class .

Cast is basically type conversion. Since our ATank “is a” APawn , we can convert from APawn to ATank via Cast. We know that this will work because we declare our ATank class in Tank.h with this line:
class BATTLETANK_API ATank : public APawn

If you tried to Cast a UStaticMesh to ATank, it wouldn’t work because ATank is not derived (not made from) a UStaticMesh .

Regarding how it finds the pawn, TankGameModeBP doesn’t find the pawn. It defines what class type the pawn will be. It’s actually our TankPlayerController that finds the pawn.

ATankPlayerController has access to GetPawn() because ATankPlayerController is derived from APlayerController, which in turn is derived from AController. You can say that ATankPlayerController is a child class of APlayerController and AController . This AController is where GetPawn() comes from. ATankPlayerController has “inherited” it from it’s parent classes.

Here’s a link to the AController in the UE4 API Reference: https://docs.unrealengine.com/latest/INT/API/Runtime/Engine/GameFramework/AController/index.html

EDIT: Removed some misleading / wrong information

3 Likes

Here’s a helpful diagram from: https://docs.unrealengine.com/latest/INT/Programming/UnrealArchitecture/ . That page gives a good overview of how the pieces fit together.

2 Likes

Thank you for putting the time and explaining, i was not clear and caused you to do more explanation work :-),
Appreciated!.

Still after your explanation,
tankBP exist somewhere else, how GetPawn() finds it?
How GetPawn() finds the tankBP?

its still not clear to me, how it access the information in TankGameModeBP that tells us where the tankBP is.
what is the “join” arrow means ?
Should I just have to take it as fact, that once we set up TankGameModeBP with some PlayerController
and some default pawn.

GetPawn() doing all the work for us ?

I will read the link you shared,
that’s just quick reply for now.

again big thanks
I hope I`m not overwhelming .

I have to admit, I do not know the exact sequence of steps that result in the World being created, when it reads the info from the GameMode, when the PlayerControllers and Pawns are created, and when the Pawn is associated with the PlayerController.

Perhaps someone else on the forum can shed some light on the World life cycle?

1 Like

The GetPawn() function does not access anything outside its own instance. Instead, what happens is:

The Engine starts and creates an instance of the game mode.
The engine then reads the default pawn from the game mode.
The engine then creates that pawn in the world.

The engine reads the default player controller from the game mode.
The engine then creates an instance of that player controller.
The engine then calles the “Posses” function on the Player Controller, passing in the earlier created pawn.

The Player controller then saves that pawn instance in a local variable.

When you call GetPawn(); all it does is it passes you the reference to the pawn that the player controller received from the engine when the last Posses was called.

There is a catch here: The Actual PlayerController class (from which our PlayerController is derived) only knows about the APawn class. It doesnt know about the ATank class. So how does that work?

Its pretty simple. This is where inheritance comes in.

You see, in c++ you can have a reference to a child class, saved in spot that holds the parent class.

So in our case, The “Pawn” (Our tank) is effectively “Cast down” from ATank to APawn the moment it is passed into the PlayerController. The player controller only has a pointer to APawn, not to ATank. That is also what the GetPawn(); returns. But underneath it is still a ATank. So you can “Cast it up” from APawn to ATank.

That is what the Cast(GetPawn()) does.

For a slightly weird analogy, think of the postal service.
The postal service knows about an address and knows that that address holds a building. It does not however know if that building is a house or an office or an appartment complex. Just that it is a building.

The postman then comes along at that address and casts it into a House, because thats what it is.

Now, if the postman tries to cast it to a house while it actually is a office building, the cast will fail.

Now to get back to reality:

The actual object itself is always ATank, but the representation that a other object has about that object can be any parent class of ATank.

The Player or AIController does not access the TankGameModeBP At all. The engine does and sets the possed pawn on the Controller in question by calling Posses();

I hope this is clearer now :slight_smile:

4 Likes

Hi mate,
thank you for the detailed explanation !

Hello Mate

I don’t quite understand why it’s failed in TankPlayerController.h file we switch on header file Tank.h and why this connection isn’t enough

and second question:

how TankPlayerController can difference Player Tank from Enemy Tank?

awesome explanations guys!!

Great explanation man!

Privacy & Terms