x

Search in
Sort by:

Question Status:

Search help

  • Simple searches use one or more words. Separate the words with spaces (cat dog) to search cat,dog or both. Separate the words with plus signs (cat +dog) to search for items that may contain cat but must contain dog.
  • You can further refine your search on the search results page, where you can search by keywords, author, topic. These can be combined with each other. Examples
    • cat dog --matches anything with cat,dog or both
    • cat +dog --searches for cat +dog where dog is a mandatory term
    • cat -dog -- searches for cat excluding any result containing dog
    • [cats] —will restrict your search to results with topic named "cats"
    • [cats] [dogs] —will restrict your search to results with both topics, "cats", and "dogs"

How do I get an instance of a playercontroller and a pawn class?

So what I want to do is basically setup a custom playercontroller inside my gamemode and then make it possess a custom pawn/character on the start of the game. (By "custom" I mean one that I have made into a seperate class.)

I am aware that I have to declare the classes in the header file but I cannot figure out how to initialize them.

Product Version: Not Selected
Tags:
more ▼

asked May 09 '15 at 06:57 PM in C++ Programming

avatar image

Dead_Cat
6 2 5 3

(comments are locked)
10|2000 characters needed characters left
Viewable by all users

2 answers: sort voted first

In order to use your custom classes, you can set the default playercontroller and pawn classes in the GameMode's constructor, e.g.

 AYourGameMode::AYourGameMode(const FObjectInitializer &ObjectInitializer)
     : Super(ObjectInitializer)
 {    
     // Set default classes to use
     DefaultPawnClass = AYourCharacter::StaticClass();
     PlayerControllerClass = AYourPlayerController::StaticClass();
 }

In order to store references to these, you can override the following functions:

header:

 // Also add includes
 ...
 #include "PWNPlayerCharacter.h"
 #include "PWNPlayerController.h"
 
 // Override SpawnPlayerController
 virtual APlayerController* SpawnPlayerController(ENetRole RemoteRole, FVector const& SpawnLocation, FRotator const& SpawnRotation) override;    
     
 // Override RestartPlayer
 virtual void RestartPlayer(class AController* NewPlayer) override;
 
 // A reference to your PlayerController
 UPROPERTY()
 AYourPlayerController* YourPlayerController; 
 
 // A reference to your Character
 UPROPERTY()
 AYourCharacter* YourCharacter;
 

cpp:

 APlayerController* AYourGameMode::SpawnPlayerController(ENetRole RemoteRole, FVector const& SpawnLocation, FRotator const& SpawnRotation)
 {
     APlayerController* pc = Super::SpawnPlayerController(RemoteRole, SpawnLocation, SpawnRotation);
     
     // Try to cast to our PC Type
     YourPlayerController = Cast<AYourPlayerController>(pc);
     return pc;
 }
 
 void AYourGameMode::RestartPlayer(AController* NewPlayer)
 {
     Super::RestartPlayer(NewPlayer);
 
     // Record expedient reference to our character
     YourCharacter = Cast<AYourCharacter>(NewPlayer->GetPawn());
 }

Naturally there are multiple other ways to achieve this as well.

more ▼

answered May 09 '15 at 09:01 PM

avatar image

staticvoidlol
2.6k 95 41 111

avatar image Dead_Cat May 09 '15 at 09:24 PM

Thanks for your reply.

I get the first part about setting the default classes but I cannot I'm getting confused about the rest. I'm not that familiar with C++ or UE4 so could you please elaborate on it?

Also I thought if you could do something like this:

Put this in the header of the gamemode:

 AYourCharacter *yourCharacter;
 AYourPlayerController *yourController;

Then initialize them (which I don't know how) and then in the cpp:

 yourController->Possess(yourCharacter);
avatar image eXi May 09 '15 at 11:54 PM

The Engine will spawn the Default PlayerController, set in the GameMode automaticly. It will also spawn and posses a pawn if the DefaultPawn is not NULL. If you want to change this behavior, you need to override the Spawn function inside the GameMode. And i guess that is what staticvoidlol is doing.

He overrides the "SpawnPlayerController" and "RestartPlayer" function, which are doing the things i mentioned above.

He is calling the "Super::" Version of the functions, which is the normal implementation from Epic inside of the parent classes (so that you don't stop the engine from spawning the classes) and adds the 2 commented lines, where he just sets the variables "YourPlayerController" and "YourCharacter" to the spawned ones.

PS: If you only want to spawn your custom classes, you only need to set them as the default classes. No need to override something. Include the header files of the two classes in the header file of the gamemode and do the DefaultPawnClass thing that staticvoidlol posted.

avatar image staticvoidlol May 10 '15 at 06:14 AM

Yes, eXi explains this very nicely. I've also updated my original post to show how you declare the references (as you already seem to know how to do) and also to include your "includes" of these classes, as they won't be referenced in the GameMode by default.

So to summarise, you can latch on to the built-in Epic functionality of spawning the controller and pawn and possessing them - you just let these routines run and afterwards you set your specific references in these overridden functions.

P.S. Overriding RestartPlayer() instead of SpawnDefaultPawnFor() to create the character reference is intentional, as in recent builds, SpawnDefaultPawnFor() is not marked as virtual anymore, so you can't really override it easily.

avatar image Dead_Cat May 10 '15 at 10:13 AM

Thanks for the reply.

So I took your code and put it into my GameMode and tt gave me 2 errors saying

APlayerController *AControllerTestGameMode::SpawnPlayerController(ENetRole RemoteRole, const FVector &SpawnLocation, const FRotator &SpawnRotation Override SpawnPlayerController

Error: member function declared with 'override' does not override a base class member

And that Super::SpawnPlayercontroller only takes two arguments: SpawnLoaction and SpawnRotation.

I removed the

 ENetRole RemoteRole

part from

 APlayerController* AYourGameMode::SpawnPlayerController(ENetRole RemoteRole, FVector const& SpawnLocation, FRotator const& SpawnRotation)

and

 RemoteRole

from

 Super::SpawnPlayerController(RemoteRole, SpawnLocation, SpawnRotation);

and it worked.

I'm not really sure what the part I remove was supposed to do?

Also how would you change the playercontroller or character afterwards?

avatar image staticvoidlol May 10 '15 at 12:45 PM

Oh ok - I see in the official documentation SpawnPlayerController() does not have RemoteRole in its signature. I suspect we're using different engine versions (I'm on the 4.8.0-preview-1 branch).

In any case, if you kept the "override" keyword at the end of the function declaration and it's compiling without problems, then it should be fine.

avatar image Dead_Cat May 10 '15 at 01:12 PM

Yeah that must be it, because I'm using 4.7.6.

How do you change the playercontroller and character during the game?

And would it be possible to do something like this so you don't have to set defaultpawnclass and playercontrollerclass:

Header:

AYourCharacter *yourCharacter; AYourPlayerController *yourController;

(Then initialize them(which I dunno how))

Cpp (possibly in BeginPlay()):

yourController->Possess(yourCharacter);

And if so how would yo initialize them?

(comments are locked)
10|2000 characters needed characters left
Viewable by all users

If you're in the gamemode you can use RestartPlayer after setting the new pawn / controller classes.

more ▼

answered May 10 '15 at 03:11 PM

avatar image

Azarus
1.9k 61 52 191

avatar image Dead_Cat May 11 '15 at 09:04 AM

Thanks for you reply. Could you please give me a code example?

avatar image staticvoidlol May 12 '15 at 06:00 AM
 AYourGameMode::YourFunction()
 {
         DefaultPawnClass = AYourCharacter::StaticClass();
        PlayerControllerClass = AYourController::StaticClass();

         YourController = SpawnPlayerController(spawnLoc, spawnRot);
         RestartPlayer(YourController);
 }
 
avatar image Dead_Cat May 12 '15 at 03:11 PM

Thanks.

Is it possible to do without changing the defaultpawnclass and the playercontrollerclass?

avatar image staticvoidlol May 12 '15 at 04:38 PM

Have you looked through the source code of GameMode.cpp?

Maybe checked out the functions like SpawnPlayerController and RestartPlayer?

Do you have any ideas you'd like to try?

I have 3 ideas that I can suggest, and it's not because I just magically know Unreal - I had to go and read through the source code to try and figure out what it does.

I don't want to sound rude, but I'd strongly suggest that you at least try to do something yourself before asking others to provide code for you. What you're doing here makes you come across as lazy. Generally people are very eager to help out, but no-one's going to code your project for you for free.

So, if you had to take a shot at it, what would you do? Let me know and I'll help out if you get stuck.

avatar image Dead_Cat May 12 '15 at 05:27 PM

Well looking at source code is not something I think I can do since I'm rather new to c++ in general.

The reason why I made this question to begin with was that I had spent days searching the internet thin, but I could find litlle no documentation about the subject. (Also in general I don't think Epic provides much documentation about what stuff does (at least to an extent where a complete newbie can make much use of it)).

Between all questions I have tried myself, and what has mostly confused me is why this doesn't work:

 AMyPlayerController * controller = new AMyPlayerController();
 AMyCharacter * character = new AMyCharacter();
 
 controller->Possess(character);

Because from what I understand that is how you would usually initialize instances of classes in c++. (If this had worked it would be simple to change characters and controllers.)

(Also I did find out myself how to change character and controller):

 void AControllerTestGameMode::BeginPlay()
 {
      CurrentCount = 1;
     PlayerControllerClass = AMyPlayerController2::StaticClass();
     DefaultPawnClass = AMyCharacter2::StaticClass();
      RestartPlayer(playercontroller2);
     SwapPlayerControllers(playercontroller, playercontroller2);
 }

And then:

         if (CurrentCount == 0)
         {
             character = Cast<AMyCharacter>(NewPlayer->GetPawn());
         }
         else if (CurrentCount == 1)
         {
             character2 = Cast<AMyCharacter2>(NewPlayer->GetPawn());
         }

in

 void AControllerTestGameMode::RestartPlayer(AController* NewPlayer)

and same just with controller in

 APlayerController* AControllerTestGameMode::SpawnPlayerController(FVector const& SpawnLocation, FRotator const& SpawnRotation)

However I hoped that the answer I would get to the code example on how to do it would be an example that did not use the PlayerControllerClass and the DefaultPawnClass, because I assumed you couldn't do it that way in multiplayer.

avatar image staticvoidlol May 12 '15 at 08:07 PM

Ok fair enough - I hear you about being new to C++ and Unreal in general, I was in that same boat a year ago, but you can pick it up fairly quickly if you make an effort. That's the main reason why I strongly suggest that you read the source code - even if it doesn't all make sense right now. The syntax and specifics will become fairly familiar after a while.

As for the Unreal codebase, yes, they do some things differently from bare C++ because they've built massive amounts of functionality into the system (like reflection, garbage collection, generics etc) and there is a lot of template usage as well. So for many things you'll need to figure out the Unreal way of doing it - however, as I've said, it becomes familiar fairly quickly.

As for the multiplayer part of your question: do you mean that for multiplayer you would be using different Pawns/Controllers depending on which avatar/class the player chooses? Multiplayer is another whole subsystem which I haven't even looked at (I'm only focusing on single player).

edit:

I think a good example would be to look at Unreal Tournament 4's source code on GitHub to see how they're handling multiple controller/character classes.

avatar image Azarus May 12 '15 at 08:12 PM

I am not a big newbie in C++ but there are code syntax that i never seen in my life :-D And he just should look at the content examples. The FPS shooter is a great example for how to do it.

avatar image Dead_Cat May 13 '15 at 07:25 PM

After realizing that both the character and playercontroller were deriving from AActor I figured you could just use SpawnActor and then SwapPlayerControllers to swap the original Playercontroller (set up with the code you provide to me earlier) with the new one and it worked!

I have had a quick look at the source code and it looks way simpler than I imagined (especially because Epic has put in alot of comments explaining the code) and it seems like the way to go as far as learning the engine is concerned.

About the multiplayer part yes that is indeed what I mean.

avatar image staticvoidlol May 14 '15 at 06:53 AM

Cool man, glad you're making progress.

Just a quick note, PlayerControllers seem very lightweight in UE4 - i.e. most of the functionality has been moved into the Pawn/Character classes, so you could probably get away with using a single PlayerController type and just swapping out Pawns/Characters.

Good luck!

(comments are locked)
10|2000 characters needed characters left
Viewable by all users
Your answer
toggle preview:

Up to 5 attachments (including images) can be used with a maximum of 5.2 MB each and 5.2 MB total.

Follow this question

Once you sign in you will be able to subscribe for any updates here

Answers to this question