Download

How to get position of all players?

Hi, I am working on multiplayer project and I need position of all players for logic. I have my specific actor for them so I know getting all actors of that type is one option, but I dont think it is good one, because I need it to be dynamic (player leaves/joins, it updates automatically) and it is highly likely I´ll be working with the positions every frame so that may be another problem.

Any help is very appreciated, thanks.

Try using FConstPlayerControllerIteratorFConstPlayerIterator to cycle through all player controlled players and get the location of their ControlledPawn(), if any.

I cant use GetWorld() for some reason, it is “undefined”.
I have these headers there and it should work according to random internet guy #15687563

#include “Engine/World.h”
#include “GameFramework/PlayerController.h”
#include “Runtime/Engine/Classes/Components/ActorComponent.h”

Any ideas why that is?

What class are you doing this in? Are you deriving your class from Uobject?

I have my own class that derives from GameModeBase and then I override PostLogin to populate an array of playercontrollers that I can use later.

I use gamemodebase as well and I did try what youre describing, but I ended up with my players starting with spectator actor instead of my own custom actor which I couldnt fix.

This a much different problem.

I too use custom pawns for players logging in.

Make sure you call the parent method via Super:: in your overriden method especially in PostLogin as that calls RestartPlayer which I had to override (and NOT call the engine’s method) so that I could use AdjustIfPossibleButAlwaysSpawn as my spawn parameter. I then had to copy some of the engines RestartPlayer functionality into my method and assign the pawn to the controller.

GameMode normally has access to GetWorld().

Head just needs basics:


// Copyright bla bla bla

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/GameModeBase.h"


So I have done as you said while also returning to adding players in PostLogin and removing them in Logout. I added these in my header file:


public:
virtual void PostLogin(APlayerController* NewPlayer) override;
virtual void Logout(AController* Exiting) override;

And these to my cpp file:


void AGameMaster::PostLogin(APlayerController* NewPlayer)
{
Super::PostLogin(NewPlayer);
Players.Add(NewPlayer);
}

void AGameMaster::Logout(AController* Exiting)
{
Super::Logout(Exiting);
APlayerController* playerController = Cast<APlayerController>(Exiting);
Players.Remove(playerController);
}

Note: Players is TArray<APlayerController*>

What happens is that my main client spawns as my custom pawn but additional clients (additional windows) do not, any idea what went wrong?

Do the additional clients/windows show the same custom pawn? I would expect that if you hardcoded the pawn class in RestartPlayer.

I override “GetDefaultPawnClassForController_Implementation” (called in RestartPlayer before the SpawnActor call) and have a setting on the playercontroller that indicates which pawn to use.

They do not, only the main (first) client spawns as the custom pawn. Also I do not understand what you mean by RestartPlayer. All I have done is set DefaultPawnClass.

So I found this in log:

LogSpawn: Warning: SpawnActor failed because of collision at the spawn location [X=0.000 Y=0.000 Z=0.000] for [Vessel]
LogGameMode: Warning: SpawnDefaultPawnAtTransform: Couldn’t spawn Pawn of type Vessel at Rotation: Pitch 0.000000 Yaw 0.000000 Roll 0.000000

Is it possible that the first pawn blocks the rest from spawning? If so how can I fix this?

That error is the reason I overrode the GameModeBase’s RestartPlayer method so that I could specify the parameter the the SpawnActor call to always spawn. Well, and to be able to specify the location of where the player is going to spawn.

And how can I override it?

The same way you override any C++ function. You did it with PostLogin and Logout.

Ye I get that, but what did you modify in the function, you said you “specified parameters of the SpawnActor call to allways spawn”. Thats what I do not understand/want to specifically know how.

Gotcha


 FActorSpawnParameters SpawnParameters;
**SpawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn;**
auto HeroClass = GetDefaultPawnClassForController(NewPlayer);

if (x != 0 && y != 0 && z != 0)
{
m_Hero = GetWorld()->SpawnActor<AAWPlayerCharacter>(HeroClass, loc
, SpawnRotation, SpawnParameters);
}

if (!m_Hero)
{
AActor* StartSpot = FindPlayerStart(NewPlayer);
SpawnRotation = StartSpot->GetActorRotation();
m_Hero = GetWorld()->SpawnActor<AAWPlayerCharacter>(HeroClass, StartSpot->GetActorLocation()
, SpawnRotation, SpawnParameters);
}



Also, I saw in your earlier post your location and rotation are all zero, origin. I doubt that you are wanting to spawn there, unless your level is perfectly flat, I guess it is possible.

Thanks! I have some questions though:

What exactly are auto HeroClass, m_Hero and StartSpot?

As for the intended spawn, right now I have large flat box as my floor, but I will have flat floor in the future as well.

I just experimented and added second PlayerStart and now it spawns all pawns… wierd…

What exactly are auto HeroClass, m_Hero and StartSpot?

HeroClass - The class used for the player’s pawn
m_Hero - the returned pawn
StartSpot is the playerstart actor selected to spawn the pawn.

Thanks for explaining! By the way I fixed my issue with pawns blocking the rest of pawns from spawning by setting my PlayerStart to allways spawn. Stupid problem to begin with but I guess I learned that at least.