What are "online beacons" and how do they work?

The idea behind beacons was to provide a lightweight way to contact a server before actually connecting “for real”.

Ideally you make a connection, send an RPC, get a response, and disconnect. You can ask things like “who is in the game” or “please make room for me, I’m about to join”. Traditionally, connecting to a server involved a full map load which can be frustrating to users if they do all that work only to be denied entry to an almost full game because someone got into the game first. Now you can make contact while still in the main menu, for example, and test multiple servers to pick the best one before joining. Or to inquire about information about a game in progress to “spectate” without being actually connected with an APlayerController and all that entails.

Gears 3 used beacons to reserve space in game. That way we could test many servers for space and travel to only one, knowing that you were definitely going to get into the game. It avoided contention when thousands of users all received the same 20-50 search results but only 10 could join per match. However, in UE3, this was TCP/IP and the protocol had to be implemented manually not using any reflection by UObject.

In UE4, we decided that our already existing network code was so robust and powerful, why reinvent the wheel? So I made the AOnlineBeacon class to leverage all the RPC and replication power of AActor.

Traditionally, actor replication and spawning has always been server initiated, meaning that you had to connect before you got a copy of an actor that the server also knew about. I wanted clients to be able to create an actor that would initiate contact with the server and fire a delegate when a connection has been made so that higher level code could make an RPC. Otherwise you’d need to make a connection with the server, wait for the server to send you an actor you could RPC with, then switch to that. Unwieldy in my opinion.

Clases of interest

AOnlineBeacon

  • the base class that clients and hosts
    derive from

AOnlineBeaconClient

  • base class that client implementations derive from
    – has its own UNetDriver that creates the connection with the server
    – has an OnConnected function that is the starting point for all game level requests to be made
    – has an OnFailure function when connection failures for any reason (before or during connection)

AOnlineBeaconHost

  • base class that hosts use to manage all beacon connections from clients
    – has its own UNetDriver listening for connections from clients
    – has a registry of AOnlineBeaconHostObjects (via RegisterHost()) that to route all traffic based on type
    – don’t typically need to derive from this class

AOnlineBeaconHostObject

  • base class for any host classes that want to handle traffic coming from an AOnlineBeaconClient
    – spawns the appropriate AOnlineBeaconClient on the server to match with the client

Examples

Check out TestBeaconClient.xxx for a very simple example. I believe QAGame project makes use of that through our UPROPERTY(Exec) function system.

void ASomeClassThatHostsBeacons::InitBeaconHost()
{
	if (Beacon)
	{
		Beacon->DestroyBeacon();
		Beacon = NULL;
	}

	// Create the hosting connection
	AOnlineBeaconHost* BeaconHost = GetWorld()->SpawnActor<AOnlineBeaconHost>(AOnlineBeaconHost::StaticClass());
	if (BeaconHost && BeaconHost->InitHost())
	{
		// Register a class to handle traffic of a specific type
		AOnlineBeaconHostObject* BeaconHostObject = GetWorld()->SpawnActor<AOnlineBeaconHostObject>(ATestBeaconHost::StaticClass());
		if (BeaconHostObject)
		{
			//BeaconHostObject->Init();
			BeaconHost->RegisterHost(BeaconHostObject);
			Beacon = BeaconHost;
		}
	}
}

void ASomeClientClassThatWantsAConnection::InitBeaconClient(FString& ServerURL)
{
	if (Beacon)
	{
		Beacon->DestroyBeacon();
		Beacon = NULL;
	}

	FURL TestURL(NULL, *ServerURL, TRAVEL_Absolute);
	Beacon = GetWorld()->SpawnActor<AOnlineBeacon>(ATestBeaconClient::StaticClass());
	if (Beacon)
	{
		Cast<ATestBeaconClient>(Beacon)->InitClient(TestURL);
	}
}

If you check the bottom of DataChannel.h there is a flow diagram for how the network connection works.

Look at NotifyControlMessage() implemented on the AOnlineBeaconClient and AOnlineBeaconHost classes to see how the handshaking works.

Once connected in this fashion, actors behave as they normally would under Unreal Network replication. Both client/server RPCs are available. Server to client replication only.

3 Likes