Testing Replication

Hi,

I’m having trouble with getting the first things networked. I basically understand the principles of replication, but I think im lacking a “starting point” to test it.

I have created a basic actor with one variable to test replicating it, but either it doesn’t replicate or I just test it wrong (which I think is the case).

TestActor.h

UCLASS()
class RTS_API ATestActor : public AActor
{
	GENERATED_BODY()
	
public:	
	ATestActor();

	virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;

	UPROPERTY(ReplicatedUsing=OnNumChanged)
	int Number = 0;

	UFUNCTION()
	void OnNumChanged();
};

Actor.cpp

#include "Net/UnrealNetwork.h"

ATestActor::ATestActor()
{
	bAlwaysRelevant = true;
	bReplicates = true;
}

void ATestActor::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
	Super::GetLifetimeReplicatedProps(OutLifetimeProps);

	DOREPLIFETIME(ATestActor, Number);
}

void ATestActor::OnNumChanged()
{
	UE_LOG(LogTemp, Warning, TEXT("Client-Num: %d"), Number);
}

I call it in my game mode (because GM only runs on server it should change the value on the server and then replicate it, correct me if I’m wrong).

void ARTSGameMode::BeginPlay()
{
	ATestActor* TestActor = NewObject<ATestActor>(this);
	TestActor->Number = 100;
}

So:

  1. Is the TestActor replicated correctly?
  2. Is the testing method with GameMode correct?
  3. How can I easily test new replicated classes without having a lot of other networked stuff from that I call events or something?

Thanks in advance!

your code looks fine to me from a replication point of view

don’t think it will work as a test
because
GameModeBeginPlay → Actor gets created → then you set the value
so what I would expect to happen is

a) all of the above happens before the client connects
so the only thing it get’s is the actor with the value already set to the correct number

or
b) client connects before begin play on GameMode
still creates the actor already with the correct value because you set the value instantly after creation and before any replication happens

for testing purposes, I would create a counter in the tick function
and let it count up
should lead you to a lot of nice OnNumChanged calls on all clients

that should answer 1

  1. depends on what you want to test, if you just want to test if values are replicated correctly you just need to spawn it on the server and then change values afterward

  2. what we at lest do, is test network scenarios and not individual replicated values, what is the expected behavior and then test if this happens, which ensures that we a) don’t start replicating things before we know that we need them, b) that we already have a test environment when we implement the replication functionallity

Thanks for your help.

I have tried it with a timer now:

void ARTSGameMode::Tick(float DeltaTime)
{
	TimeElapsed += DeltaTime;
	if (TimeElapsed >= 5.f && !HasPlaced) {
		HasPlaced = true;
		TestActor = NewObject<ATestActor>(this);
		UE_LOG(LogTemp, Warning, TEXT("Spawned"));
	}
	if (TimeElapsed >= 8.f && !HasChanged) {
		HasChanged = true;
		TestActor->Number = 100;
		UE_LOG(LogTemp, Warning, TEXT("Changed"));
	}
}

“Spawned” and “Changed” get logged, but still nothing gets called on the client.

I just noticed that the actor doesn’t exist in the world outliner after it gets spawned, not sure if this is correct.

In the log I get this warning a lot when I start the game:

LogOnlineSession: Warning: OSS: No game present to join for session (GameSession)

Not sure if this can be causing the problem, but the Actors and their movement from the samplescene replicates properly.
I saw some posts about this warning, but they all seem to occur when they host a dedicated server on their own, but I’m just using the default engine “multiplayer”.

Do you have an idea about all that or should I maybe open a new topic for this?

didn’t see that on my first look
try replacing the

TestActor = NewObject<ATestActor>(this);

with one of the SpawnActor functions in UWorld

e.g.
GetWorld()->SpawnActor(ATestActor::StaticClass());

Alright, that worked. Really thanks a lot!

Just if you are interested:
The timer is unnecessary. Was wondering when you wrote this, because that’s the “advantage” of OnRep Functions. Contrary to Multicasts, OnRep functions get always called when “needed”, so when you join the server later or if you are outside of the cull-distance and come in the cull-distance its also called.

Have a nice day!

thanks, wasn’t sure about first-time replication
good to know