k, that was more painful than expected
First I tried to make a nice non intrusive utility function which just calls the correct functions on the playercontroller and be done with it, but ofc nothing is ever easy…
I ran full frontal into that problem [Spectator Pawn On Client Side][1], so long story short. As far as I can see there is no way to use spectating “correctly” without creating your own PlayerController class. To use my solution you will need to inherit your PlayerController from the class I added below, or you can also just add the code to your implementation of a PlayerController if you already have one. An example how to use it would be in my github test project [here][2] in the StartSpectating folder.
StartSpectatingPlayerController.h
#pragma once
#include "GameFramework/PlayerController.h"
#include "StartSpectatingPlayerController.generated.h"
UCLASS()
class AStartSpectatingPlayerController : public APlayerController
{
GENERATED_BODY()
public:
virtual void OnRep_Pawn() override;
UFUNCTION(BlueprintCallable, Category = "Start Spectating Player Controller")
void StartSpectating();
UFUNCTION(Client, Reliable)
void Client_StartSpectating();
UFUNCTION(BlueprintCallable, Category = "Start Spectating Player Controller")
void StartPlaying();
};
StartSpectatingPlayerController.cpp
#include "StartSpectatingPlayerController.h"
#include "GameFramework/SpectatorPawn.h"
void AStartSpectatingPlayerController::OnRep_Pawn()
{
Super::OnRep_Pawn();
if (GetStateName() == NAME_Spectating)
{
AutoManageActiveCameraTarget(GetSpectatorPawn());
}
}
void AStartSpectatingPlayerController::StartSpectating()
{
if (!HasAuthority())
return;
ChangeState(NAME_Spectating);
Client_StartSpectating();
}
void AStartSpectatingPlayerController::StartPlaying()
{
if (!HasAuthority())
return;
ChangeState(NAME_Playing);
ClientGotoState(NAME_Playing);
}
void AStartSpectatingPlayerController::Client_StartSpectating_Implementation()
{
if (PlayerCameraManager)
SetSpawnLocation(PlayerCameraManager->GetCameraLocation());
ChangeState(NAME_Spectating);
}
and an example how to use it
more elaborate example with switching to spectator mode and going back