Spawn different actor in different place

Hi

I’m trying to figure out how to spawn two different actor using my game mode, i have a soldier character and a thief one, and once the map is loaded i’d like to spaw for the client the thief character and for the server the slodier, i`ve read that there is a SpawnDefaultPawnFor(AController* NewPlayer, class AActor* StartSpot) to spawn actors but i don’t know how to use it. Can someone help me ?

Thanks

Game Mode Multiple Spawn Points

Here’s some code that works as long as you have multiple player starts in your level!

//your game mode.h




//I am overriding Game Mode virtual functions, you dont have to call them, Game Mode class calls them whenever a player joins.

/** select best spawn point for player */
	virtual AActor* ChoosePlayerStart(AController* Player) override;

	/** always */
	virtual bool PlayerCanRestart(APlayerController* Player) override;
	
	/** check if player can use spawnpoint */
	virtual bool IsSpawnpointAllowed(APlayerStart* SpawnPoint, AController* Player) const;

	/** check if player should use spawnpoint */
	virtual bool IsSpawnpointPreferred(APlayerStart* SpawnPoint, AController* Player) const;


//your game mode.cpp




//adjust to your preferences, could make into variable to be tweaked in BP
#define TOO_CLOSE_RADIUS 128

bool AGalaxyGameMode::PlayerCanRestart(APlayerController* Player)
{
	return true;
}

/** Choosing Start Point */
AActor* AGalaxyGameMode::ChoosePlayerStart(AController* Player)
{
	//If PIE, dont do this, so "play from here" works
	if(GetWorld()->WorldType == EWorldType::PIE)
	{
		return Super::ChoosePlayerStart(Player);
		//~~~~~~~~~~~~~~~~~~~~~~~
	}
	 
	static TArray<APlayerStart*> PreferredSpawns;
	static TArray<APlayerStart*> FallbackSpawns;
	PreferredSpawns.Reset();
	FallbackSpawns.Reset();

	for (int32 i = 0; i < PlayerStarts.Num(); i++)
	{
		APlayerStart* TestSpawn = PlayerStarts*;
		if (IsSpawnpointAllowed(TestSpawn, Player))
		{
			if (IsSpawnpointPreferred(TestSpawn, Player))
			{
				PreferredSpawns.Add(TestSpawn);
			}
			else
			{
				FallbackSpawns.Add(TestSpawn);
			}
		}
	}

	APlayerStart* BestStart = NULL;
	if (PreferredSpawns.Num() > 0)
	{
		BestStart = PreferredSpawns[FMath::RandHelper(PreferredSpawns.Num())];
	}
	else if (FallbackSpawns.Num() > 0)
	{
		BestStart = FallbackSpawns[FMath::RandHelper(FallbackSpawns.Num())];
	}

	return BestStart ? BestStart : Super::ChoosePlayerStart(Player);
}
bool AGalaxyGameMode::IsSpawnpointAllowed(APlayerStart* SpawnPoint, AController* Player) const
{
	if(!SpawnPoint) return false;
	//~~~~~~~~~~~~~~~
	
	//Character Proximity?
	for (TActorIterator<ACharacter> Itr(GetWorld()); Itr; ++Itr)
	{
		//Check if there's any player within TOO_CLOSE_RADIUS
		if ((SpawnPoint->GetActorLocation() - Itr->GetActorLocation()).SizeSquared() < TOO_CLOSE_RADIUS *TOO_CLOSE_RADIUS) 
		{
			return false;
		}
		
	}
	
	//~~~
	
	//Test if there is any World Geometry in the way of the spawn Point!
	FHitResult Hit;
	return UVictoryCore::VTrace(SpawnPoint,
		SpawnPoint->GetActorLocation() + FVector(0,0,256), 
		SpawnPoint->GetActorLocation() - FVector(0,0,256), 
		Hit								
	); 
	
	
	

}
 
bool AGalaxyGameMode::IsSpawnpointPreferred(APlayerStart* SpawnPoint, AController* Player) const
{
	if(!SpawnPoint) return false;
	 
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	//Last Resort Spawn Point!
	if(SpawnPoint->GetName().Contains("LastResortSpawnPoint")) return false;
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	
	ACharacter* MyPawn = Player ? Cast<ACharacter>(Player->GetPawn()) : NULL;
	if (MyPawn)
	{
		const FVector MyLocation = MyPawn->GetActorLocation();
		for (FConstPawnIterator It = GetWorld()->GetPawnIterator(); It; ++It)
		{
			ACharacter* OtherPawn = Cast<ACharacter>(*It);
			if (OtherPawn && OtherPawn != MyPawn)
			{
				const float CombinedHeight = (MyPawn->GetCapsuleComponent()->GetScaledCapsuleHalfHeight() + OtherPawn->GetCapsuleComponent()->GetScaledCapsuleHalfHeight()) * 2.0f;
				const float CombinedRadius = MyPawn->GetCapsuleComponent()->GetScaledCapsuleRadius() + OtherPawn->GetCapsuleComponent()->GetScaledCapsuleRadius();
				const FVector OtherLocation = OtherPawn->GetActorLocation();

				// check if player start overlaps this pawn
				if (FMath::Abs(MyLocation.Z - OtherLocation.Z) < CombinedHeight && (MyLocation - OtherLocation).Size2D() < CombinedRadius)
				{
					return false;
				}
				
				//Check if there's any player within TOO_CLOSE_RADIUS
				if(SpawnPoint)
				{
					if ((SpawnPoint->GetActorLocation() - OtherLocation).SizeSquared() < TOO_CLOSE_RADIUS * TOO_CLOSE_RADIUS) 
					{
						return false;
					}
				}
			}
		}
	}

	return true;
}




**For You To Do**

You can replace my custom C++ library function, UVictoryCore::VTrace(), with GetWorld()->LineTraceSingle

**
What This Does**

Basically when a player wants to spawn, server or as many clients as you want, the code checks all the player starts and finds one that is not occupied, by verifying there is no colliding geometry in way, and also making sure there are no characters that are with TOO_CLOSE_RADIUS of the spawn point

You can tweak the TOO_CLOSE_RADIUS part or remove it as you see fit.

You could also use the Character’s Scaled Capsule Radius



float CapsuleRadius = Character->GetCapsuleComponent()->GetScaledCapsuleRadius();

//Remember to use **CapsuleRadius * CapsuleRadius** since it is a Size Squared check!



**Not in PIE**

Notice I skip my code if PIE is being used, so that "play from here" works

You should test using Standalone or running the game from commandline to see my code working correctly.

Enjoy!

Rama

Thanks very much for your help, the spawn work perfectly, but i have a problem to spawn two different actor, i’ve followed your tutorial to assign character via blueprint, but it only work for single player A new, community-hosted Unreal Engine Wiki - Announcements and Releases - Unreal Engine Forums
I’ve made this code


AQuietOpsGameMode::AQuietOpsGameMode(const FObjectInitializer& ObjectInitializer)
	: Super(ObjectInitializer)
{
	// set default pawn class to our Blueprinted character

	PlayerControllerClass = ADefaultPlayerController::StaticClass();

	for (FConstPlayerControllerIterator Iterator = GetWorld()->GetPlayerControllerIterator(); Iterator; ++Iterator)
	{
		ADefaultPlayerController*	MyCharacter = Cast<ADefaultPlayerController>(*Iterator);
		if (MyCharacter->imThief)
		{
			static ConstructorHelpers::FClassFinder<APawn> PlayerPawnBPClass(TEXT("/Game/Blueprints/ThiefCharacter"));
			if (PlayerPawnBPClass.Class != NULL)
			{
				DefaultPawnClass = PlayerPawnBPClass.Class;
				
			}

		}
		else if (MyCharacter->imAnesthesist)
		{
			static ConstructorHelpers::FClassFinder<APawn> PlayerPawnBPClass(TEXT("/Game/Blueprints/AnesthesistCharacter"));
			if (PlayerPawnBPClass.Class != NULL)
			{
				DefaultPawnClass = PlayerPawnBPClass.Class;
			
			}
		}
	}
}

but it raise an exception, because the world in not fully instantiate and i’m trying to acces to it, then where should i put my loop, to load two different pawn depending on the players choices ?