Loading...
Loading...
Unreal Engine networking specialist - Masters Actor replication, GameMode/GameState architecture, server-authoritative gameplay, network prediction, and dedicated server setup for UE5
npx skill4agent add sharadchaturveda-coder/agency-agents-codex agency-unreal-multiplayer-architectUFUNCTION(Server)ReplicationGraphFRepMovementUPROPERTY(Replicated)ReplicatedUsingUFUNCTION(Server, Reliable, WithValidation)WithValidation_Validate()HasAuthority()NetMulticastUPROPERTY(Replicated)UPROPERTY(ReplicatedUsing=OnRep_X)GetNetPriority()SetNetUpdateFrequency()DOREPLIFETIME_CONDITIONCOND_OwnerOnlyCOND_SimulatedOnlyGameModeGameStatePlayerStatePlayerControllerReliableUnreliable// AMyNetworkedActor.h
UCLASS()
class MYGAME_API AMyNetworkedActor : public AActor
{
GENERATED_BODY()
public:
AMyNetworkedActor();
virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;
// Replicated to all — with RepNotify for client reaction
UPROPERTY(ReplicatedUsing=OnRep_Health)
float Health = 100.f;
// Replicated to owner only — private state
UPROPERTY(Replicated)
int32 PrivateInventoryCount = 0;
UFUNCTION()
void OnRep_Health();
// Server RPC with validation
UFUNCTION(Server, Reliable, WithValidation)
void ServerRequestInteract(AActor* Target);
bool ServerRequestInteract_Validate(AActor* Target);
void ServerRequestInteract_Implementation(AActor* Target);
// Multicast for cosmetic effects
UFUNCTION(NetMulticast, Unreliable)
void MulticastPlayHitEffect(FVector HitLocation);
void MulticastPlayHitEffect_Implementation(FVector HitLocation);
};
// AMyNetworkedActor.cpp
void AMyNetworkedActor::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
DOREPLIFETIME(AMyNetworkedActor, Health);
DOREPLIFETIME_CONDITION(AMyNetworkedActor, PrivateInventoryCount, COND_OwnerOnly);
}
bool AMyNetworkedActor::ServerRequestInteract_Validate(AActor* Target)
{
// Server-side validation — reject impossible requests
if (!IsValid(Target)) return false;
float Distance = FVector::Dist(GetActorLocation(), Target->GetActorLocation());
return Distance < 200.f; // Max interaction distance
}
void AMyNetworkedActor::ServerRequestInteract_Implementation(AActor* Target)
{
// Safe to proceed — validation passed
PerformInteraction(Target);
}// AMyGameMode.h — Server only, never replicated
UCLASS()
class MYGAME_API AMyGameMode : public AGameModeBase
{
GENERATED_BODY()
public:
virtual void PostLogin(APlayerController* NewPlayer) override;
virtual void Logout(AController* Exiting) override;
void OnPlayerDied(APlayerController* DeadPlayer);
bool CheckWinCondition();
};
// AMyGameState.h — Replicated to all clients
UCLASS()
class MYGAME_API AMyGameState : public AGameStateBase
{
GENERATED_BODY()
public:
virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;
UPROPERTY(Replicated)
int32 TeamAScore = 0;
UPROPERTY(Replicated)
float RoundTimeRemaining = 300.f;
UPROPERTY(ReplicatedUsing=OnRep_GamePhase)
EGamePhase CurrentPhase = EGamePhase::Warmup;
UFUNCTION()
void OnRep_GamePhase();
};
// AMyPlayerState.h — Replicated to all clients
UCLASS()
class MYGAME_API AMyPlayerState : public APlayerState
{
GENERATED_BODY()
public:
UPROPERTY(Replicated) int32 Kills = 0;
UPROPERTY(Replicated) int32 Deaths = 0;
UPROPERTY(Replicated) FString SelectedCharacter;
};// In Character header — AbilitySystemComponent must be set up correctly for replication
UCLASS()
class MYGAME_API AMyCharacter : public ACharacter, public IAbilitySystemInterface
{
GENERATED_BODY()
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="GAS")
UAbilitySystemComponent* AbilitySystemComponent;
UPROPERTY()
UMyAttributeSet* AttributeSet;
public:
virtual UAbilitySystemComponent* GetAbilitySystemComponent() const override
{ return AbilitySystemComponent; }
virtual void PossessedBy(AController* NewController) override; // Server: init GAS
virtual void OnRep_PlayerState() override; // Client: init GAS
};
// In .cpp — dual init path required for client/server
void AMyCharacter::PossessedBy(AController* NewController)
{
Super::PossessedBy(NewController);
// Server path
AbilitySystemComponent->InitAbilityActorInfo(GetPlayerState(), this);
AttributeSet = Cast<UMyAttributeSet>(AbilitySystemComponent->GetOrSpawnAttributes(UMyAttributeSet::StaticClass(), 1)[0]);
}
void AMyCharacter::OnRep_PlayerState()
{
Super::OnRep_PlayerState();
// Client path — PlayerState arrives via replication
AbilitySystemComponent->InitAbilityActorInfo(GetPlayerState(), this);
}// Set replication frequency per actor class in constructor
AMyProjectile::AMyProjectile()
{
bReplicates = true;
NetUpdateFrequency = 100.f; // High — fast-moving, accuracy critical
MinNetUpdateFrequency = 33.f;
}
AMyNPCEnemy::AMyNPCEnemy()
{
bReplicates = true;
NetUpdateFrequency = 20.f; // Lower — non-player, position interpolated
MinNetUpdateFrequency = 5.f;
}
AMyEnvironmentActor::AMyEnvironmentActor()
{
bReplicates = true;
NetUpdateFrequency = 2.f; // Very low — state rarely changes
bOnlyRelevantToOwner = false;
}# DefaultGame.ini — Server configuration
[/Script/EngineSettings.GameMapsSettings]
GameDefaultMap=/Game/Maps/MainMenu
ServerDefaultMap=/Game/Maps/GameLevel
[/Script/Engine.GameNetworkManager]
TotalNetBandwidth=32000
MaxDynamicBandwidth=7000
MinDynamicBandwidth=4000
# Package.bat — Dedicated server build
RunUAT.bat BuildCookRun
-project="MyGame.uproject"
-platform=Linux
-server
-serverconfig=Shipping
-cook -build -stage -archive
-archivedirectory="Build/Server"GetLifetimeReplicatedPropsDOREPLIFETIME_CONDITION_Validatestat netp.NetShowCorrections 1_Validate_Validate()FNetworkPredictionStateBaseUReplicationGraphNode_GridSpatialization2DUReplicationGraphNodenet.RepGraph.PrintAllNodesAOnlineBeaconHostUGameInstanceUGameplayAbilityFPredictionKeyFGameplayEffectContextUGameplayAbilitynet.stats