Unreal Network

Intro #

  • Unreal network system is based on Server-Client model.
  • If developers consider about “Replication”, game can support both singleplayer and multiplayer.
  • UE4 Clients can not communicate without Server (p2p is not currently supported)

Struct #

Network Mode #

  • ENetMode
    • NM_Standalone
      • Authoritative : true
      • Listening : false
      • LocalPlayer : true
    • NM_DedicatedServer
      • Authoritative : true
      • Listening : true
      • LocalPlayer : false
    • NM_ListenServer
      • Authoritative : true
      • Listening : true
      • LocalPlayer : true
    • NM_Client
      • Authoritative : false
      • Listening : false
      • LocalPlayer : true
    • NM_MAX

Role, RemoteRole #

  • ENetRole
    • ROLE_None
      • not related with replication
    • ROLE_SimulatedProxy
      • copy of ROLE_Authority
      • extrapolative-predicted with server values
    • ROLE_AutonomousProxy
      • copy of ROLE_Authority
      • extrapolative-predicted with server values + local functions (e.g. player input)
      • currently, only for possessed actor with ownership
    • ROLE_Authority
      • origin
      • not available for NM_Client currently
    • ROLE_MAX

Ownership #

  • PlayerController is root of ownership
    • Pawn that possessed by PlayerController and Actors owned by the Pawn is owned by the Player
    • Subobjects owned by its outer’s owner
  • needed for
    • Client RPC destination
    • replication relevancy
      • bOnlyRelevantToOwner
    • conditional property replication
      • COND_OwnerOnly, COND_InitialOrOwner, COND_SkipOwner
    • ROLE_AutonomousProxy to ROLE_SimulatedProxy
      • ROLE_AutonomousProxy is only allowed for owner client

Method #

Property Replication #

class ENGINE_API AActor : public UObject
{
    UPROPERTY( Replicated ) // originally, it's ReplicatedWith specifier
    AActor * Owner;

    UPROPERTY(EditDefaultsOnly, ReplicatedUsing=OnRep_ReplicatedMovement, Category=Replication, AdvancedDisplay)
    struct FRepMovement ReplicatedMovement;

    UFUNCTION()
    virtual void OnRep_ReplicatedMovement();
};

void AActor::GetLifetimeReplicatedProps( TArray< FLifetimeProperty > & OutLifetimeProps ) const
{
    DOREPLIFETIME( AActor, Owner );
    DOREPLIFETIME_CONDITION( AActor, ReplicatedMovement, COND_SimulatedOnly );
	// check "UnrealNetwork.h" for more variations
}

void AActor::PreReplication( IRepChangedPropertyTracker & ChangedPropertyTracker )
{
    DOREPLIFETIME_ACTIVE_OVERRIDE( AActor, ReplicatedMovement, bReplicateMovement );
}

void AActor::OnRep_ReplicatedMovement() { ... }
  • server to client only
  • reliable
  • ELifetimeCondition
    • COND_None
    • COND_InitialOnly
    • COND_OwnerOnly
    • COND_SkipOwner
    • COND_SimulatedOnly
    • COND_AutonomousOnly
    • COND_SimulatedOrPhysics
    • COND_InitialOrOwner
    • COND_Custom + SetCustonIsActiveOverride(...)
    • COND_ReplayOrOwner
    • COND_ReplayOnly
    • COND_SimulatedOnlyNoReplay
    • COND_SimulatedOrPhysicsNoReplay
    • COND_SkipReplay
    • COND_Never
    • COND_Max
  • NetUpdateFrequency
    • and MinNetUpdateFrequency for Adaptive Network Frequency
  • with UPROPERTY(replicated), UObject references are replicated via FNetworkGUID
    • check with UObject::IsSupportedForNetwork()
    • refernce replication occurs in one of them :
      • replicated actor
      • stably named actor
      • replicated component
      • stably named component
      • UObject from loaded package
    • “stably named” means
      • existing in both server and client with exactly same name
      • actors from package are stably named (not spawned during gameplay)
      • components under are stably named
        • from package
        • added with construction script (static component)
        • manually marked (via UActorComponent::SetNetAddressable(...))
          • need same name

Remote Procedure Call (RPC) #

UFUNCTION(Server, WithValidation)
void FunctionThatCalledOnServer();

UFUNCTION(Client, Reliable)
void FunctionThatCalledOnOwnerClient();

UFUNCTION(NetMulticast)
void FunctionThatCalledOnEveryActor();

void ClassName::FunctionThatCalledOnServer_Implementation() {}
bool ClassName::FunctionThatCalledOnServer_Validation() {return true;}
void ClassName::FunctionThatCalledOnOwnerClient_Implementation() {}
void ClassName::FunctionThatCalledOnEveryActor_Implementation() {}
  • Only executed on Actor that is replicating
  • If you want to make sure RPC executed. you should set Reliable specifier on RPC’s UFUNCTION().
    • RPC is Unreiiable by default.
    • If you spam Reliable like every ticks, client may get disconnected due to preventation of DDOS.
  • WithValidation specifier declares _Validation function with bool return and same parameters.
    • _Validation function must be followed after WithValidation specifier.
    • disconnect client if return is false
    • execute RPC if return is true
    • Server RPC requires WithValidation
  • when calling RPC on Server
    actor \ specifiernoneNetMulticastServerClient
    Owned by clientserverserver & all clientsserverowning client
    Owned by serverserverserver & all clientsserverserver
    Unownedserverserver & all clientsserverserver
  • when calling RPC on Client
    actor \ specifiernoneNetMulticastServerClient
    Owned by selfselfselfserverself
    Owned by otherselfselfnoneself
    Owned by serverselfselfnoneself
    Unownedselfselfnoneself

Component Replication #

  • tbd

Optimization #

Relevancy #

  • AActor::IsNetRelevantFor()
    1. return true : bIsAlwaysRelevant | Owned | Pawn | Instigated by Pawn
    2. return owner’s : bNetUseOwnerRelevancy & Owned
    3. return false : bOnlyRelevantToOwner & not 1.
    4. return base’s : attached to skeleton of another actor
    5. return false : bHidden & root component not collide
      • warning if there is no root component
    6. return ture : distance based relevancy (AGameNetworkManager) & closer than net cull distance
  • Pawn and PlayerController return different result (overriding)
  • bStatic Actors can also be replicated
  • imperfect
    • large actor
    • sound occlusion of ambient sound
    • though, packet loss is more critical so it’s affordable

Priority #

  • NetPriority
  • weight for bandwidth load balancing
  • default values
    • Actor = 1.0
    • Matinee = 2.7
    • Pawn = 3.0
    • PlayerController = 3.0
  • AActor::GetNetPriority() = NetPriority * replication waiting time (plus location and distance, etc)

Dormancy #

  • ENetDormancy
    • DORM_Never
    • DORM_Awake
    • DORM_DormantAll
    • DORM_DormantPartial + GetNetDormancy()
    • DORM_Initial
    • DORM_Max

NetClientTicksPerSecond #

  • tbd

Replication Graph #

  • tbd

Conceptual Tips #

  • reduce bReplicates
  • reduce NetUpdateFrequency
  • use Dormancy
  • use Relevancy
  • reduce NetClientTicksPerSecond
  • use Quantizing (e.g. FVector_NetQuantize)
  • minimize RPC : replace into RepNotify
    • remove Server RPC that unused on clients
    • reduce NetMulticast RPC
    • reduce FName as RPC parameter
    • don’t spam reliable RPC
  • check ROLE_Authority for server logic
  • check IsLocallyControlled for owner logic
    • but not in constructor

Flow #

UNetDriver::ServerReplicateActors flow #

  • tbd

Character Movement Component flow #

  • tbd

Others #

Travelling #

  • Seamless (non-blocking)
    • highly recommended
  • Non-Seamless (blocking)
    • first map loading
    • client-to-server first connect
    • ending game, starting new game
  • UEngine::Browse(...)
  • UWorld::ServerTravel(...)
  • APlayerController::ClientTravel(...)
  • Transition Map
    • UGameMapSetting::TransitionMap
    • AGameModeBase::bUseSeamlessTravel
  • Seamless Travel Flow
    1. Mark persistent actors to transition map
    2. Travel to transition map
    3. Mark persistent actors to final map
    4. Travel to final map
  • Persistent actors
    • GameMode actor (server only)
      • Actors added by AGameModeBase::GetSeamlessTravelActorList
    • Controllers with valid PlayerState (server only)
    • All PlayerControllers (server only)
    • All local PlayerControllers (server and clients)
      • Actors added by APlayerController::GetSeamlessTravelActorList on local

Online Subsystem #

  • tbd

Session #

  • tbd

Online Beacons #

  • tbd

Practical #

Network Profiler #

  • tbd

Testing Multiplay #

  • tbd