PlayerState returns None on Client's Controller

At the listen server’s PlayerController it works well. But not with the Client’s one.

I saw a very similar question, but without answer to the question: https://answers.unrealengine.com/questions/182954/player-state-casting-fails-on-event-begin-play.html
Isn’t it supposed to work like this?

Execute on Owning Client is supposed to be used only by the server and not the client. If you execute an Event with Run on Owning Client on a client, it won’t be different than executing a regular function. It’s not like it will give you an error but have that in mind.

It is weird though, player state is automatically replicated from server to client. Maybe just maybe, if you are executing this at the very very start of the game, maybe the first player state replication hasn’t arrived yet, try using a small delay before using the player state

The GameMode calls this event during OnPostLogin, and I want to put widget showing function here too, this is why it is called from server to client. It could be an explanation, I didn’t think about that the state is late from the party. But I hate these delays, so I guess I’ll try to make a new event for widget creation, and only that will run on the client. But still, the replication order should be modified in the engine then, in my opinion.

Hi!
Two things:

  1. Use OnRep_Noptify to be sure the MyNumber has been replicated, then when it fires you will have your value on the client

  2. I use timers on the client during setup to ensure the playerstate has been replicated:
    if(playerState)
    {
    DoClientLogic();
    }
    else
    {
    SetTimerForFunctions();//I usually waits like 0.2 seconds before trying again.
    }

OnRep_Notify only fires when the value changes not when it has been replicated. This is an initial setup so there’s no chance an OnRep will fire at this point in the code.

Initially I have for example
MyTeam = ETeam::Undefined;

And then changes it to MyTeam = ETeam::Team1;

then onrep notify fires on client and the value is set.

Oh and ONLY set the value on server side, then you’ll have a repnotify event on client.

Did i miss something?

@State128: The problem is, the reference to the PlayerState doesn’t arrive in time for the OnPostLogin. My other problem was that the client also needs MyNumber instantly. When the normal variable replicating starts, it’s already too late, because some textures set themselves based on this.
In the end, this was the solution that works perfectly:

This way the client gets instantly the variable and sets it locally too, so every other blueprint can use it before the normal variable replication arrives. And also I don’t need to call the PlayerState’s init event on the client.

There HAS to be a better solution than using delays and timers. Is there a Rep Notify for when Playerstate’s are initially ready to be used when players login?

Update: Found a solution! Check the answer I posted.

UP, did you get a solution for this Rep Notify when playerstate’s are initialized?

Solution found!

https://api.unrealengine.com/INT/API/Runtime/Engine/GameFramework/AController/OnRep_PlayerState/index.html

:slight_smile:

This will make your dreams come true. It fixed a lot of issues for me. This is a function that gets called when PlayerState is replicated. You can make an event out of this and notify your code that PlayerState has been replicated in Blueprints.

Bad news: It’s not exposed in BP. So you need to expose it yourself using some C++.

Good news: It’s very easy to do so.

For C++ programmers this should be easy so this is for BP devs:

  1. Go to UE4 Editor and make a C++ class that’s based off of PlayerController.
  2. Make an event dispatcher that you will broadcast from CPP and listen to from BP.
  3. Expose the event dispatcher to Blueprints
  4. Extend OnRep_PlayerState() which is a prebuilt function that gets called when PlayerState gets replicated.
  5. Call Super::OnRep_PlayerState(); to make sure prebuilt logic still gets executed since we are only extending the method
  6. Broadcast the event dispatcher.
  7. Compile
  8. In BP, make your main PlayerController BP extend this class.
  9. Bind to this event. It should be called according to how you named your event dispatcher variable.

It should look something like this:

// MasterPlayerController.h
#pragma once

#include "CoreMinimal.h"
#include "GameFramework/PlayerController.h"
#include "MasterPlayerController.generated.h"

DECLARE_DYNAMIC_MULTICAST_DELEGATE(FRepPlayerState);

/**
 * 
 */
UCLASS()
class KRIEG_API AMasterPlayerController : public APlayerController
{
	GENERATED_BODY()

public:
	
	void OnRep_PlayerState() override;

	UPROPERTY(BlueprintAssignable, BlueprintCallable)
	FRepPlayerState RepPlayerState;
};



// MasterPlayerController.cpp

#include "MasterPlayerController.h"

void AMasterPlayerController::OnRep_PlayerState()
{
	Super::OnRep_PlayerState();
	RepPlayerState.Broadcast();
}

@GTNardy

4 Likes

@GTNardy Yes! Check the answer :slight_smile: Thanks for reminding me to post the answer.