Architecture Overview

Get an overview of the architecture powering SnapNet’s Unreal Engine SDK

The main entry point to SnapNet functionality from within Unreal Engine is via the SnapNet Subsystem—a subclass of UGameInstanceSubsystem which means there will be one created automatically per UGameInstance.

The SnapNet Subsystem initializes a SnapNet Server and SnapNet Client, each of which contain a SnapNet Simulation to drive the underlying networked gameplay simulation in isolation from each other and the final rendering.

The following diagram illustrates these relationships:

Diagram of the SnapNet Unreal Engine SDK architecture

Multiple worlds

The separation of simulation and presentation is central to SnapNet’s architecture. The Unreal Engine SDK addresses this by creating multiple UWorlds.

In a traditional Unreal game there is generally a single UWorld—the loaded map—containing the actors and their collision data, the physics scene, navigation data, etc. SnapNet uses this main world for presentation but creates additional UWorlds for the client and server simulations, enabling each to maintain their own set of actors, collision, and physics simulations. Critically, it also allows them to be ticked at different rates.

Accessing worlds

When using multiple UWorlds, you need to take care to reference the correct UWorld when performing operations. The following sections cover how to determine which UWorld contains a given object and how to explicitly retrieve the client and server’s UWorld.

Determine a UObject’s world

To access the world containing a given UObject call:

UWorld* World = GEngine->GetWorldFromContextObjectChecked( Obj );

These methods can be used to determine whether an object is contained in the client world or the server world:

if ( USnapNetSubsystem::IsSnapNetClient( Obj ) )
{
    // Object is in the client world
}
else if ( USnapNetSubsystem::IsSnapNetServer( Obj ) )
{
    // Object is in the server world
}
else
{
    // Object is in the main (presentation) world
}

Access the client and server worlds

To retrieve a pointer to either the client or server UWorld, first get a pointer to the USnapNetClient or USnapNetServer:

USnapNetClient* Client = USnapNetClient::Get( Obj );

USnapNetServer* Server = USnapNetServer::Get( Obj );

These functions return pointers to the USnapNetClient and USnapNetServer objects even if the specified object is not in the corresponding world.

Once you have a USnapNetClient or USnapNetServer you can access the UWorld via its simulation:

// Client
UWorld* ClientWorld = Client->GetSimulation()->GetOwnedWorld();

// Server
UWorld* ServerWorld = Server->GetSimulation()->GetOwnedWorld();