MiniTurtle
(MiniTurtle)
September 19, 2014, 11:57am
1
Hey,
I have a server that sends a PlayerId to a client and I need the client to get the player, like this:
(Now this below works, I was wondering if there already was something like this built in or a faster way to do it.)
int32 PlayerID = AMyCharacter->PlayerState->PlayerId
AMyCharacter *GetPlayer(int32 PlayerID)
{
for (auto Actor : GetWorld()->NetworkActors)
{
AMyCharacter *Player = Cast<AMyCharacter>(Actor);
if (Player && Player->PlayerState->PlayerId == PlayerID)
return Player;
}
}
I figured I could make a TArray PlayerList
in gamestate but I don’t want to duplicate things that already exist in UE4
Please suggest something.
Thank you for your time
The world object has a PlayerControllerIterator that should be consistent across all clients. You can iterate over that if you want.
MiniTurtle
(MiniTurtle)
September 23, 2014, 8:03am
3
I’m sorry for the delayed reply (computer problems ;P)
I assume that you mean this:
for (auto ControllerIt = GetWorld()->GetPlayerControllerIterator();
ControllerIt; ++ControllerIt)
{
APlayerController *Controller = *ControllerIt;
if (Controller->PlayerState->PlayerId == PlayerID)
{
return Cast<AMyCharacter>(Controller->GetPawn());
}
}
It never finds the player (doesn’t work)
MiniTurtle
(MiniTurtle)
September 23, 2014, 8:10am
4
So far only iterating NetworkActors has worked for me.
Here are some other ways I tried:
This also “works” but it gets a copy (server & client has the same player pointer)
TArray<APlayerController *> PlayerList;
GEngine->GetAllLocalPlayerControllers(PlayerList);
for (auto Controller : PlayerList)
{
if (Controller->PlayerState->PlayerId == PlayerID)
{
APawn *Pawn = Controller->GetPawn();
return Cast<AMyCharacter>(Pawn);
}
}
This finds the player but Controller is always NULL
(In game state)
for (auto PlayerState : PlayerArray)
{
if (PlayerState->PlayerId == PlayerID)
{
AController *Controller = PlayerState->GetInstigatorController();
return Cast<AMyCharacter>(Controller->GetPawn());
}
}
MiniTurtle
(MiniTurtle)
September 23, 2014, 3:32pm
5
I ended up with this solution:
AMyCharacter *GetPlayer(int32 PlayerID)
{
for (auto PlayerState : PlayerArray)
{
if (PlayerState->PlayerId == PlayerID)
{
AMyPlayerState*PS = Cast<AMyPlayerState>(PlayerState);
if (!PS)
return NULL;
#ifdef WITH_SERVER_CODE
if (Role == ROLE_Authority)
{
APlayerController *PC = PS->ParentController.Get(false);
if (!PC)
return NULL;
return Cast<AMyCharacter>(PC->GetPawn());
}
#endif
#if !UE_SERVER
return PS->ParentPlayer.Get(false);
#endif
return NULL;
}
}
}
(MyPlayerState.h)
public:
#ifdef WITH_SERVER_CODE
TWeakObjectPtr<APlayerController> ParentController;
#endif
#if !UE_SERVER
TWeakObjectPtr<class AMyCharacter> ParentPlayer;
#endif
};
(MyGameMode.cpp)
void AMyGameMode::StartNewPlayer(APlayerController* NewPlayer)
{
Super::StartNewPlayer(NewPlayer); // Remember this, if forgotten HUD is disabled ;P
AMyPlayerState *PS = Cast<AMyPlayerState>(NewPlayer->PlayerState);
if (PS)
PS->ParentController = NewPlayer;
}
(MyCharacter.cpp)
void AMyCharacter::OnRep_PlayerState()
{
Super::OnRep_PlayerState();
#if !UE_SERVER
AMyPlayerState *PS = Cast<AMyPlayerState>(PlayerState);
if (PS)
PS->ParentPlayer = this;
#endif
}
sinoth
(sinoth)
January 27, 2015, 10:16pm
6
Interesting solution! Really a shame that something like this isn’t built in… it seems strange there there is no easy way to go from a PlayerState to the possessed pawn. I wonder if this is because we are using the PlayerState in a way it wasn’t intended? I have a similar question here .