CategoriesC++Unreal Engine

Syncing random (animation) between clients.

In multiplayer projects there are cases when you need sync random (not only for animations) between clients; The first and the obvious idea is to use Random Stream and seed; But there’s a question how to sync the seed between clients and also make it unique for all actors that will be in use of it. The solution is simple and elegant.

Firstly we need to uniquly identify Actors between the clients and server.

C++
int32 UPB_BlueprintFunctionLibrary::GetNetGIUD(UObject* WorldContextObject, AActor * InActor)
{
	UWorld* World = WorldContextObject->GetWorld();
	
	if(!World->IsGameWorld())
	{
		return 0;
	}
	
	FNetworkGUID NetId = World->GetNetDriver()->GuidCache->GetOrAssignNetGUID(InActor);
	int32 Seed = NetId.ObjectId;
	int32 Default = FNetworkGUID::GetDefault().ObjectId;
	
	// can't find NetGUID in NetGUIDLookup, default was assigned
	ensureAlways(Seed != Default);
	
	return Seed;
}

Nice already. But there’s no guaranty that this seed will be unique between the game launches. The solution is below:

C++
// PB_GameState.h:
protected:
  UPROPERTY(Replicated)
  int32 RandomSessionSeed = 0;
  
public:
  UFUNCTION(BlueprintPure, Category="Game session")
  int32 GetRandomSessionSeed();
  
// PB_GameState.cpp:
int32 APB_GameState::GetRandomSessionSeed()
{
	if(!bRandomSessionSeedWasGenerated && HasAuthority())
	{
		RandomSessionSeed = FMath::RandRange(-1000000, 1000000);
		bRandomSessionSeedWasGenerated = true;
	}
	return RandomSessionSeed;
}

And how to use it:

C++
FRandomStream RandomStream;
int32 NetGUID = UPB_BlueprintFunctionLibrary::GetNetGIUD(this, this);
int32 RandomSessionSeed = GetWorld()->GetGameState<APB_GameState>()->GetRandomSessionSeed();
int32 Seed = NetGUID + RandomSessionSeed;
RandomStream.Initialize(Seed);

UMaterialInstance* Material = RandomSkins[RandomStream.RandRange(0, RandomSkins.Num() - 1)];
GetMesh()->SetMaterial(0, Material);

And for syncing random animations playback between clients:

And finally, animations are synced between client:

Leave a Reply

Your email address will not be published. Required fields are marked *