Online Beacons provide a lightweight mechanism for clients to communicate with servers without committing to a normal Unreal Engine (UE) network game connection. Online beacons derive from the actor class and provide a base framework. You can extend the framework in derived classes, so they can perform project-specific interactions and information requests. Some common use cases for online beacons include:
-
Calculating connection ping.
-
Reserving a spot in a game session.
-
Querying information about a game session or lobby before joining.
Typically, actor replication and spawning is initiated by an authoritative server. Since the server is usually authoritative, a client must connect to a server to first obtain a copy of an actor that the server has authority over. Online beacons work differently by providing clients with a system to create an actor that initiates contact with a server, then fires a delegate so the server beacon can call a Remote Procedure Call (RPC) immediately after a client connects.
Class Structure
The online beacon framework has the following structure:
Online Beacon
Online Beacon is the base class for both AOnlineBeaconClient
and AOnlineBeaconHost
. You typically don’t need to override the online beacon itself, since you can override the online beacon client and online beacon host individually.
Online Beacon Client
An online beacon client is the base class from which client implementations derive. This is the primary working class of the online beacon system.
This class has its own UNetDriver
that initiates connection with the server. Once a connection between a client's and a server's copy of an online beacon client object is made, replication of the objects behaves like ordinary UE replication. Both the server and the client can call RPCs and the server's version of the online beacon client object is authoritative over property replication.
You typically spawn an online beacon client in client gameplay code, then connect to an online beacon host on the server with the AOnlineBeaconClient::InitClient
function. You need to specify the online beacon client class you are using in your online beacon host object constructor so the server knows which client class to spawn and communicate with the client machine. You can override the AOnlineBeaconClient::OnConnected
function to call RPCs as soon as a connection is established between server and client. You can also override the AOnlineBeaconClient::OnFailure
function to perform custom failure handling.
Online Beacon Host
Online beacon host is the base class hosts use to manage all beacon connections from clients. Online beacon host manages a registry of online beacon host objects to route traffic based on the type of online beacon client currently requesting a connection and communicating with the online beacon host.
The class has its own UNetDriver that listens for connections from clients. When an online beacon host receives a connection from a remote machine's online beacon client, the host scans its registry of online beacon host object instances to determine which one matches the incoming client, then transfers management of the connection to that online beacon host object.
You typically spawn an online beacon host in server gameplay code, for example, in your game mode class.
Online Beacon Host Object
Online beacon host object is the base class for any host classes that handle traffic coming from an online beacon client.
This class spawns the appropriate online beacon client on the server to match the online beacon client on the client machine that initiated the connection. Online beacon host objects use the ClientBeaconActorClass
member variable to determine the online beacon client class actor to spawn.
You typically spawn an online beacon host object in server gameplay code after you spawn an online beacon host, then register the online beacon host object with the online beacon host. Once an online beacon client connects to the online beacon host object that a delegate fires, and calls the AOnlineBeaconHostObject::OnClientConnected
function. You can then call an RPC to initiate communication between client and host inside this function.
Engine Example
Unreal Engine provides a small online beacon implementation in the header files TestBeaconClient.h
and TestBeaconHost.h
in the directory:
..\Engine\Plugins\Online\OnlineSubsystemUtils\Source\OnlineSubsystemUtils\Classes\
The implementations are contained in the associated .cpp
files in the directory:
..\Engine\Plugins\Online\OnlineSubsystemUtils\Source\OnlineSubsystemUtils\Private\
The test beacon implementation repeatedly calls RPCs back-and-forth between a server and a client, printing a short log message each time. The following section describes what you must do to spawn test beacons in your gameplay code.
Spawn Test Beacons
To use the TestBeaconClient
and TestBeaconHost
classes in your project, follow these steps:
-
In your server gameplay code, spawn an
ATestBeaconHost
. -
In your client gameplay code, spawn an
ATestBeaconClient
. -
Connect the client to the server with a call to
ATestBeaconClient::InitClient(url)
in your client gameplay code, whereurl
is aFURL
object with the server's address and port.
Once you click Begin Play, your gameplay code spawns a test beacon host on the server and a test beacon client on every client. The following section describes the resulting process flow that automatically occurs between the test beacons.
Process Flow of Test Beacons
This section describes the process flow after your game spawns the test beacons when you begin play:
-
First, the
ATestBeaconHost
constructor sets the member variableClientBeaconActorClass
to the classATestBeaconClient
and sets theBeaconTypeName
member variable toClientBeaconActorClass->GetName()
. This ensures that the online beacon system pairs the test beacon host and test beacon client classes together so the server spawns the correct client class to match the client class initiating a connection. -
When a client machine's
ATestBeaconClient
object contacts the server, the server'sAOnlineBeaconHost
instance directs the registeredATestBeaconHost
to spawn its ownATestBeaconClient
and associate it with theATestBeaconClient
on the client machine. There is now a test beacon client on the client machine, and a test beacon client on the server machine. Furthermore, the network connection facilitates client and server RPCs to pass information between the twoATestBeaconClient
instances. -
Next, the server's
ATestBeaconHost
callsATestBeaconHost::OnClientConnected
. Within the functionATestBeaconHost::OnClientConnected
, the server's test beacon client instance initiates a ping with a call to the client RPCClientPing
. -
When the client machine's
ATestBeaconClient
instance receives the RPC and executes theATestBeaconClient::ClientPing_Implementation
, the client's test beacon client first printsLogBeacon: Ping
in the client log, then calls the server RPCServerPong
. -
Last, when the server machine's
ATestBeaconClient
instance receives the RPC and executes theATestBeaconClient::ServerPong_Validate
function, the server validates that the program is not running in a shipping configuration. If the validation succeeds, thenATestBeaconClient::ServerPong_Implementation
executes. Within the functionATestBeaconClient::ServerPong_Implementation
, the server's beacon client first printsLogBeacon: Pong
in the server log, then calls the client RPCClientPing
. This call toClientPing
causes the previous bullet point and this one to repeat.
This process continues indefinitely, and provides an example of an online beacon implementation that you can expand upon in any way that suits your project's needs.
If you want to stop the process after one back-and-forth, you can remove the call to ClientPing
in the ATestBeaconClient::ServerPong_Implementation
.
In addition to this engine example, this documentation page provides a step-by-step implementation guide for online beacons in the Implement an Online Beacon section below.
Engine Configuration
To use online beacons in your project, you must first configure them. There are several engine configuration options available.
To start configuring an online beacon, add the following to your project's DefaultEngine.ini file:
[/Script/Engine.Engine]
+NetDriverDefinitions=(DefName="BeaconNetDriver",DriverClassName="/Script/OnlineSubsystemUtils.IpNetDriver",DriverClassNameFallback="/Script/OnlineSubsystemUtils.IpNetDriver")
[/Script/OnlineSubsystemUtils.OnlineBeacon]
BeaconConnectionInitialTimeout=30.0
BeaconConnectionTimeout=45.0
;[/Script/OnlineSubsystemUtils.OnlineBeaconClient]
;BeaconConnectionInitialTimeout=
;BeaconConnectionTimeout=
[/Script/OnlineSubsystemUtils.OnlineBeaconHost]
ListenPort=8888
bReuseAddressAndPort=false
bAuthRequired=false
MaxAuthTokenSize=1024
Configuration Reference
This section explains what each of the above configuration options are used for, and how you should configure them for your project.
Engine
The following configures the beacon network driver to drive network traffic for online beacons:
[/Script/Engine.Engine]
+NetDriverDefinitions=(DefName="BeaconNetDriver",DriverClassName="/Script/OnlineSubsystemUtils.IpNetDriver",DriverClassNameFallback="/Script/OnlineSubsystemUtils.IpNetDriver")
This example uses the IpNetDriver
as the network driver class. To use a different network driver class, specify the class you would like to use in the DriverClassName
field.
Online Beacon
Field | Description |
---|---|
Beacon Connection Initial Timeout | Time the beacon waits to establish a connection with the beacon host. |
Beacon Connection Timeout | Time the beacon waits for packets after establishing a connection before giving up. |
Online Beacon Client
Field | Description |
---|---|
Beacon Connection Initial Timeout | Time the beacon waits to establish a connection with the beacon host. |
Beacon Connection Timeout | Time the beacon waits for packets after establishing a connection before giving up. |
Online Beacon Host
Field | Description | Default Value |
---|---|---|
Listen Port | Configured listen port for this beacon host. | |
Reuse Address and Port | Whether to configure the listening socket to allow reuse of the address and port. If this is true, make sure that no other servers can run on the same port, otherwise this can lead to undefined behavior since packets will go to two servers. |
false |
Auth Required | Set this to true if you require clients to negotiate auth prior to joining the beacon. | false |
Max Auth Token Size | Maximum authentication token size. Only used if Auth Required is set to true. | 1024 |
Ensure that the Listen Port configured for your online beacon host is the same as the port you are passing in the FURL
object to your online beacon client's InitClient
function.
Implement an Online Beacon
This section contains a sample implementation of an online beacon to calculate server-client ping round-trip time (RTT). The round-trip time is the amount of time it takes for a packet to be sent from client to server and then back to the client again. This is a small implementation and only provides a brief introduction to what online beacons are capable of, but it aims to give you a working example to get you started with an implementation beyond the test beacon and adds to it by explaining how to set up online beacons in your gameplay code.
This online beacon sample is implemented with a combination of C++ and Blueprints and makes use of UE's reflection system Function Metadata Specifiers and Class Metadata Specifiers for both Remote Procedure Calls and exposing certain functions to Blueprint Visual Scripting.
To implement a ping program with Unreal Engine's online beacons, follow these steps:
-
Create or open an Unreal Engine C++ project.
-
Use the C++ Class Wizard to create three new C++ classes:
-
A class titled
PingClient
derived fromOnlineBeaconClient
. -
A class titled
PingHost
derived fromOnlineBeaconHost
. -
A class titled
PingHostObject
derived fromOnlineBeaconHostObject
.
-
-
Add the code in the Ping Beacon Code section to the respective header and source files:
-
Add the following function to your project's game mode file:
Header
public:
bool InitPingBeacon();
Source
bool ABeaconsGameMode::InitPingBeacon()
{
ENetMode Mode = GetNetMode();
if (Mode == NM_DedicatedServer || Mode == NM_ListenServer)
{
APingHost* Host = GetWorld()->SpawnActor<APingHost>(APingHost::StaticClass());
if (Host && Host->InitializeHost())
{
APingHostObject* HostObject = GetWorld()->SpawnActor<APingHostObject>(APingHostObject::StaticClass());
if (HostObject)
{
Host->RegisterHostObject(HostObject);
return true;
}
}
}
return false;
}
-
In your game mode's
BeginPlay
function, call theInitPingBeacon
. -
Make sure that you have configured your project to use online beacons by adding the configuration in the Engine Configuration section to your project's
DefaultEngine.ini
file. -
Add the following to a Blueprint that only runs in your client game instance. This sample used the Third Person Template, so this code is added to the BP_ThirdPersonCharacter:
Begin Object Class=/Script/BlueprintGraph.K2Node_Event Name="K2Node_Event_0" ExportPath="/Script/BlueprintGraph.K2Node_Event'/Game/ThirdPerson/Blueprints/BP_ThirdPersonCharacter.BP_ThirdPersonCharacter:EventGraph.K2Node_Event_0'" EventReference=(MemberParent="/Script/CoreUObject.Class'/Script/Engine.Actor'",MemberName="ReceiveBeginPlay") bOverrideFunction=True NodePosY=400 bCommentBubblePinned=True NodeGuid=641371E6411FC9D89F0E5D8323049C98 CustomProperties Pin (PinId=EAE8F3034FC01AF83136C48DCE1F4D73,PinName="OutputDelegate",Direction="EGPD_Output",PinType.PinCategory="delegate",PinType.PinSubCategory="",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(MemberParent="/Script/CoreUObject.Class'/Script/Engine.Actor'",MemberName="ReceiveBeginPlay"),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,) CustomProperties Pin (PinId=9CB66600479CAAE192CD17823296C033,PinName="then",Direction="EGPD_Output",PinType.PinCategory="exec",PinType.PinSubCategory="",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,LinkedTo=(K2Node_CallFunction_6 2C9B940A4D10AADA10399B9F60FF49B2,),PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,) End Object Begin Object Class=/Script/BlueprintGraph.K2Node_CustomEvent Name="K2Node_CustomEvent_0" ExportPath="/Script/BlueprintGraph.K2Node_CustomEvent'/Game/ThirdPerson/Blueprints/BP_ThirdPersonCharacter.BP_ThirdPersonCharacter:EventGraph.K2Node_CustomEvent_0'" CustomFunctionName="PingEvent" NodePosY=640 NodeGuid=5BD80F5F4A8B9348E5367C9EE7DC3751 CustomProperties Pin (PinId=824C3E73438BE917D9901C8BA2796843,PinName="OutputDelegate",Direction="EGPD_Output",PinType.PinCategory="delegate",PinType.PinSubCategory="",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(MemberParent="/Script/Engine.BlueprintGeneratedClass'/Game/ThirdPerson/Blueprints/BP_ThirdPersonCharacter.BP_ThirdPersonCharacter_C'",MemberName="PingEvent",MemberGuid=5BD80F5F4A8B9348E5367C9EE7DC3751),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,) CustomProperties Pin (PinId=46F29CF244DDEB00F0E5CC8CEBBAA58A,PinName="then",Direction="EGPD_Output",PinType.PinCategory="exec",PinType.PinSubCategory="",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,LinkedTo=(K2Node_SpawnActorFromClass_1 6921F0194B69A0C1E9CBD281626EDCAB,),PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,) End Object Begin Object Class=/Script/BlueprintGraph.K2Node_SpawnActorFromClass Name="K2Node_SpawnActorFromClass_1" ExportPath="/Script/BlueprintGraph.K2Node_SpawnActorFromClass'/Game/ThirdPerson/Blueprints/BP_ThirdPersonCharacter.BP_ThirdPersonCharacter:EventGraph.K2Node_SpawnActorFromClass_1'" NodePosX=400 NodePosY=656 AdvancedPinDisplay=Shown NodeGuid=622DC95C46F608CD70500B85132FE4AB CustomProperties Pin (PinId=6921F0194B69A0C1E9CBD281626EDCAB,PinName="execute",PinType.PinCategory="exec",PinType.PinSubCategory="",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,LinkedTo=(K2Node_CustomEvent_0 46F29CF244DDEB00F0E5CC8CEBBAA58A,),PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,) CustomProperties Pin (PinId=1B3133C841C35D6F68FBAA951831056B,PinName="then",Direction="EGPD_Output",PinType.PinCategory="exec",PinType.PinSubCategory="",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,LinkedTo=(K2Node_CallFunction_2 7BF417FF432C7400B87C71942FF836E1,),PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,) CustomProperties Pin (PinId=CB9D54F4483152E7E290B19FE3D48E8A,PinName="Class",PinToolTip="Actor Class Reference Class\nThe object class you want to construct",PinType.PinCategory="class",PinType.PinSubCategory="",PinType.PinSubCategoryObject="/Script/CoreUObject.Class'/Script/Engine.Actor'",PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,DefaultObject="/Script/Beacons.PingClient",PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,) CustomProperties Pin (PinId=15498E3B40C28CDE28E01FAE73E81DA6,PinName="ReturnValue",PinToolTip="Ping Client Object Reference Return Value\nThe constructed object",Direction="EGPD_Output",PinType.PinCategory="object",PinType.PinSubCategory="",PinType.PinSubCategoryObject="/Script/CoreUObject.Class'/Script/Beacons.PingClient'",PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,LinkedTo=(K2Node_CallFunction_2 912DBB9D44B68DDD0328E7A816CF7516,),PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,) CustomProperties Pin (PinId=85DB02094AD8D6D9C91E7690AC574D53,PinName="SpawnTransform",PinToolTip="Spawn Transform\nTransform\n\nThe transform to spawn the Actor with",PinType.PinCategory="struct",PinType.PinSubCategory="",PinType.PinSubCategoryObject="/Script/CoreUObject.ScriptStruct'/Script/CoreUObject.Transform'",PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,LinkedTo=(K2Node_CallFunction_0 ADDA843B4E2A91753356DC91FE3B9F9A,),PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,) CustomProperties Pin (PinId=C1443292474BFB8DF2E9F79921A536C4,PinName="CollisionHandlingOverride",PinToolTip="Collision Handling Override\nESpawnActorCollisionHandlingMethod Enum\n\nSpecifies how to handle collisions at the spawn point. If undefined, uses actor class settings.",PinType.PinCategory="byte",PinType.PinSubCategory="",PinType.PinSubCategoryObject="/Script/CoreUObject.Enum'/Script/Engine.ESpawnActorCollisionHandlingMethod'",PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,DefaultValue="AlwaysSpawn",PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,) CustomProperties Pin (PinId=9F905FBB499C1BF279F85FAF726E858A,PinName="TransformScaleMethod",PinType.PinCategory="byte",PinType.PinSubCategory="",PinType.PinSubCategoryObject="/Script/CoreUObject.Enum'/Script/Engine.ESpawnActorScaleMethod'",PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,DefaultValue="MultiplyWithRoot",PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=True,bOrphanedPin=False,) CustomProperties Pin (PinId=1858F883407DA2A78DAD709E45BB7237,PinName="Owner",PinToolTip="Owner\nActor Object Reference\n\nCan be left empty; primarily used for replication (bNetUseOwnerRelevancy and bOnlyRelevantToOwner), or visibility (PrimitiveComponent's bOwnerNoSee/bOnlyOwnerSee)",PinType.PinCategory="object",PinType.PinSubCategory="",PinType.PinSubCategoryObject="/Script/CoreUObject.Class'/Script/Engine.Actor'",PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,LinkedTo=(K2Node_CallFunction_1 EEF081514454872D386B6BAC6475269B,),PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=True,bOrphanedPin=False,) CustomProperties Pin (PinId=8E61DCAF48C40C5B72D5BDB2790625F9,PinName="Instigator",PinToolTip="Instigator\nPawn Object Reference\n\nPawn responsible for damage and other gameplay events caused by this actor.",PinType.PinCategory="object",PinType.PinSubCategory="",PinType.PinSubCategoryObject="/Script/CoreUObject.Class'/Script/Engine.Pawn'",PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=True,PinType.bSerializeAsSinglePrecisionFloat=False,AutogeneratedDefaultValue="None",PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,) End Object Begin Object Class=/Script/BlueprintGraph.K2Node_CallFunction Name="K2Node_CallFunction_0" ExportPath="/Script/BlueprintGraph.K2Node_CallFunction'/Game/ThirdPerson/Blueprints/BP_ThirdPersonCharacter.BP_ThirdPersonCharacter:EventGraph.K2Node_CallFunction_0'" bIsPureFunc=True FunctionReference=(MemberParent="/Script/CoreUObject.Class'/Script/Engine.KismetMathLibrary'",MemberName="MakeTransform") NodePosX=-16 NodePosY=784 NodeGuid=7DE9226B45AE997BBFFC8F9EBC136078 CustomProperties Pin (PinId=073C80F04E9A08AC3FB622A1F2EE93FD,PinName="self",PinFriendlyName=NSLOCTEXT("K2Node", "Target", "Target"),PinToolTip="Target\nKismet Math Library Object Reference",PinType.PinCategory="object",PinType.PinSubCategory="",PinType.PinSubCategoryObject="/Script/CoreUObject.Class'/Script/Engine.KismetMathLibrary'",PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,DefaultObject="/Script/Engine.Default__KismetMathLibrary",PersistentGuid=00000000000000000000000000000000,bHidden=True,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,) CustomProperties Pin (PinId=29FC17024B8B7D876C41F4BC093C6C3A,PinName="Location",PinToolTip="Location\nVector",PinType.PinCategory="struct",PinType.PinSubCategory="",PinType.PinSubCategoryObject="/Script/CoreUObject.ScriptStruct'/Script/CoreUObject.Vector'",PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,DefaultValue="0, 0, 0",AutogeneratedDefaultValue="0, 0, 0",PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,) CustomProperties Pin (PinId=9D78DF6440AE198D4CBDE8984F8C1354,PinName="Rotation",PinToolTip="Rotation\nRotator",PinType.PinCategory="struct",PinType.PinSubCategory="",PinType.PinSubCategoryObject="/Script/CoreUObject.ScriptStruct'/Script/CoreUObject.Rotator'",PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,DefaultValue="0, 0, 0",AutogeneratedDefaultValue="0, 0, 0",PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,) CustomProperties Pin (PinId=EE9D68A648FC7948FC0F8B961CB343F8,PinName="Scale",PinToolTip="Scale\nVector",PinType.PinCategory="struct",PinType.PinSubCategory="",PinType.PinSubCategoryObject="/Script/CoreUObject.ScriptStruct'/Script/CoreUObject.Vector'",PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,DefaultValue="1.000000,1.000000,1.000000",AutogeneratedDefaultValue="1.000000,1.000000,1.000000",PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,) CustomProperties Pin (PinId=ADDA843B4E2A91753356DC91FE3B9F9A,PinName="ReturnValue",PinToolTip="Return Value\nTransform\n\nMake a transform from location, rotation and scale",Direction="EGPD_Output",PinType.PinCategory="struct",PinType.PinSubCategory="",PinType.PinSubCategoryObject="/Script/CoreUObject.ScriptStruct'/Script/CoreUObject.Transform'",PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,LinkedTo=(K2Node_SpawnActorFromClass_1 85DB02094AD8D6D9C91E7690AC574D53,),PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,) End Object Begin Object Class=/Script/BlueprintGraph.K2Node_CallFunction Name="K2Node_CallFunction_1" ExportPath="/Script/BlueprintGraph.K2Node_CallFunction'/Game/ThirdPerson/Blueprints/BP_ThirdPersonCharacter.BP_ThirdPersonCharacter:EventGraph.K2Node_CallFunction_1'" bIsPureFunc=True FunctionReference=(MemberParent="/Script/CoreUObject.Class'/Script/Engine.GameplayStatics'",MemberName="GetPlayerController") NodePosX=32 NodePosY=1024 NodeGuid=E3356F124ADCE9C464182D8154699FF3 CustomProperties Pin (PinId=4865E66F4AEE74634193CDAD2E2AA1D3,PinName="self",PinFriendlyName=NSLOCTEXT("K2Node", "Target", "Target"),PinToolTip="Target\nGameplay Statics Object Reference",PinType.PinCategory="object",PinType.PinSubCategory="",PinType.PinSubCategoryObject="/Script/CoreUObject.Class'/Script/Engine.GameplayStatics'",PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,DefaultObject="/Script/Engine.Default__GameplayStatics",PersistentGuid=00000000000000000000000000000000,bHidden=True,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,) CustomProperties Pin (PinId=975B63044778CD73752315A2E8C21922,PinName="WorldContextObject",PinToolTip="World Context Object\nObject Reference",PinType.PinCategory="object",PinType.PinSubCategory="",PinType.PinSubCategoryObject="/Script/CoreUObject.Class'/Script/CoreUObject.Object'",PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=True,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,PersistentGuid=00000000000000000000000000000000,bHidden=True,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,) CustomProperties Pin (PinId=38468A6B43840A13F2F5A8982372AC2A,PinName="PlayerIndex",PinToolTip="Player Index\nInteger\n\nIndex in the player controller list, starting first with local players and then available remote ones",PinType.PinCategory="int",PinType.PinSubCategory="",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,DefaultValue="0",AutogeneratedDefaultValue="0",PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,) CustomProperties Pin (PinId=EEF081514454872D386B6BAC6475269B,PinName="ReturnValue",PinToolTip="Return Value\nPlayer Controller Object Reference",Direction="EGPD_Output",PinType.PinCategory="object",PinType.PinSubCategory="",PinType.PinSubCategoryObject="/Script/CoreUObject.Class'/Script/Engine.PlayerController'",PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,LinkedTo=(K2Node_SpawnActorFromClass_1 1858F883407DA2A78DAD709E45BB7237,),PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,) End Object Begin Object Class=/Script/BlueprintGraph.K2Node_CallFunction Name="K2Node_CallFunction_2" ExportPath="/Script/BlueprintGraph.K2Node_CallFunction'/Game/ThirdPerson/Blueprints/BP_ThirdPersonCharacter.BP_ThirdPersonCharacter:EventGraph.K2Node_CallFunction_2'" FunctionReference=(MemberParent="/Script/CoreUObject.Class'/Script/Beacons.PingClient'",MemberName="ConnectToHost") NodePosX=896 NodePosY=640 NodeGuid=B53D30824E8D128AAD972D84938717C4 CustomProperties Pin (PinId=7BF417FF432C7400B87C71942FF836E1,PinName="execute",PinToolTip="\nExec",PinType.PinCategory="exec",PinType.PinSubCategory="",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,LinkedTo=(K2Node_SpawnActorFromClass_1 1B3133C841C35D6F68FBAA951831056B,),PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,) CustomProperties Pin (PinId=EB2F70EC4C0559D2F2FDA6A9D3675560,PinName="then",PinToolTip="\nExec",Direction="EGPD_Output",PinType.PinCategory="exec",PinType.PinSubCategory="",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,LinkedTo=(K2Node_IfThenElse_0 AF9A40FC4AEFE89DC7CD8CB714050FA9,),PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,) CustomProperties Pin (PinId=912DBB9D44B68DDD0328E7A816CF7516,PinName="self",PinFriendlyName=NSLOCTEXT("K2Node", "Target", "Target"),PinToolTip="Target\nPing Client Object Reference",PinType.PinCategory="object",PinType.PinSubCategory="",PinType.PinSubCategoryObject="/Script/CoreUObject.Class'/Script/Beacons.PingClient'",PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,LinkedTo=(K2Node_SpawnActorFromClass_1 15498E3B40C28CDE28E01FAE73E81DA6,),PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,) CustomProperties Pin (PinId=143602B4486FF90CD92A7BB633B53355,PinName="Address",PinToolTip="Address\nString",PinType.PinCategory="string",PinType.PinSubCategory="",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,DefaultValue="127.0.0.1",PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,) CustomProperties Pin (PinId=10CC29914E051D2BD6B4BB891C2632DC,PinName="Port",PinToolTip="Port\nInteger",PinType.PinCategory="int",PinType.PinSubCategory="",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,DefaultValue="8888",AutogeneratedDefaultValue="0",PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,) CustomProperties Pin (PinId=A5CF1278499613AB178B859DAD4F2992,PinName="bPortOverride",PinToolTip="Port Override\nBoolean",PinType.PinCategory="bool",PinType.PinSubCategory="",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=True,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,DefaultValue="false",AutogeneratedDefaultValue="false",PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,) CustomProperties Pin (PinId=F90880E847BCED344DC098969DB9B54D,PinName="ReturnValue",PinToolTip="Return Value\nBoolean\n\nConnect to Host",Direction="EGPD_Output",PinType.PinCategory="bool",PinType.PinSubCategory="",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,DefaultValue="false",AutogeneratedDefaultValue="false",LinkedTo=(K2Node_IfThenElse_0 3B5D7EE74E3F3C2075C3C3AEEC871F4F,),PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,) End Object Begin Object Class=/Script/BlueprintGraph.K2Node_IfThenElse Name="K2Node_IfThenElse_0" ExportPath="/Script/BlueprintGraph.K2Node_IfThenElse'/Game/ThirdPerson/Blueprints/BP_ThirdPersonCharacter.BP_ThirdPersonCharacter:EventGraph.K2Node_IfThenElse_0'" NodePosX=1280 NodePosY=656 NodeGuid=C6BF80FE4F382A2E83AC98975F7D87ED CustomProperties Pin (PinId=AF9A40FC4AEFE89DC7CD8CB714050FA9,PinName="execute",PinType.PinCategory="exec",PinType.PinSubCategory="",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,LinkedTo=(K2Node_CallFunction_2 EB2F70EC4C0559D2F2FDA6A9D3675560,),PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,) CustomProperties Pin (PinId=3B5D7EE74E3F3C2075C3C3AEEC871F4F,PinName="Condition",PinType.PinCategory="bool",PinType.PinSubCategory="",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,DefaultValue="true",AutogeneratedDefaultValue="true",LinkedTo=(K2Node_CallFunction_2 F90880E847BCED344DC098969DB9B54D,),PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,) CustomProperties Pin (PinId=FE97970843E6292D14CFFE8E7068EFCE,PinName="then",PinFriendlyName=NSLOCTEXT("K2Node", "true", "true"),Direction="EGPD_Output",PinType.PinCategory="exec",PinType.PinSubCategory="",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,LinkedTo=(K2Node_CallFunction_3 E56D58EC46817A042829E998B205166D,),PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,) CustomProperties Pin (PinId=14F8E61C4470196AB44FE18C78F330F0,PinName="else",PinFriendlyName=NSLOCTEXT("K2Node", "false", "false"),Direction="EGPD_Output",PinType.PinCategory="exec",PinType.PinSubCategory="",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,LinkedTo=(K2Node_CallFunction_4 4B794A1547001A751BB1E3A5D3FCB42F,),PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,) End Object Begin Object Class=/Script/BlueprintGraph.K2Node_CallFunction Name="K2Node_CallFunction_3" ExportPath="/Script/BlueprintGraph.K2Node_CallFunction'/Game/ThirdPerson/Blueprints/BP_ThirdPersonCharacter.BP_ThirdPersonCharacter:EventGraph.K2Node_CallFunction_3'" FunctionReference=(MemberParent="/Script/CoreUObject.Class'/Script/Engine.KismetSystemLibrary'",MemberName="PrintString") NodePosX=1536 NodePosY=576 AdvancedPinDisplay=Hidden EnabledState=DevelopmentOnly NodeGuid=206D8F0743AE9399F810DE9D7DBF0AE6 CustomProperties Pin (PinId=E56D58EC46817A042829E998B205166D,PinName="execute",PinToolTip="\nExec",PinType.PinCategory="exec",PinType.PinSubCategory="",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,LinkedTo=(K2Node_IfThenElse_0 FE97970843E6292D14CFFE8E7068EFCE,),PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,) CustomProperties Pin (PinId=607ECD45490CBD9CD664ECA9C39C17A6,PinName="then",PinToolTip="\nExec",Direction="EGPD_Output",PinType.PinCategory="exec",PinType.PinSubCategory="",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,) CustomProperties Pin (PinId=0D455D4043C4BE74B10178942F346710,PinName="self",PinFriendlyName=NSLOCTEXT("K2Node", "Target", "Target"),PinToolTip="Target\nKismet System Library Object Reference",PinType.PinCategory="object",PinType.PinSubCategory="",PinType.PinSubCategoryObject="/Script/CoreUObject.Class'/Script/Engine.KismetSystemLibrary'",PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,DefaultObject="/Script/Engine.Default__KismetSystemLibrary",PersistentGuid=00000000000000000000000000000000,bHidden=True,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,) CustomProperties Pin (PinId=58B310A540E92F72FF7551A3F3BD9562,PinName="WorldContextObject",PinToolTip="World Context Object\nObject Reference",PinType.PinCategory="object",PinType.PinSubCategory="",PinType.PinSubCategoryObject="/Script/CoreUObject.Class'/Script/CoreUObject.Object'",PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=True,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,PersistentGuid=00000000000000000000000000000000,bHidden=True,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,) CustomProperties Pin (PinId=C22FBEB34F7353659494C2ACB91CFAE2,PinName="InString",PinToolTip="In String\nString\n\nThe string to log out",PinType.PinCategory="string",PinType.PinSubCategory="",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,DefaultValue="Success to Connect to Host",AutogeneratedDefaultValue="Hello",PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,) CustomProperties Pin (PinId=3F42942C44C5E4CBDD01BA864C025CCB,PinName="bPrintToScreen",PinToolTip="Print to Screen\nBoolean\n\nWhether or not to print the output to the screen",PinType.PinCategory="bool",PinType.PinSubCategory="",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,DefaultValue="true",AutogeneratedDefaultValue="true",PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=True,bOrphanedPin=False,) CustomProperties Pin (PinId=95BE02A243BAFF7E750EA78B0369C60E,PinName="bPrintToLog",PinToolTip="Print to Log\nBoolean\n\nWhether or not to print the output to the log",PinType.PinCategory="bool",PinType.PinSubCategory="",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,DefaultValue="true",AutogeneratedDefaultValue="true",PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=True,bOrphanedPin=False,) CustomProperties Pin (PinId=48620995452AADD79E31708B07358AD0,PinName="TextColor",PinToolTip="Text Color\nLinear Color Structure\n\nThe color of the text to display",PinType.PinCategory="struct",PinType.PinSubCategory="",PinType.PinSubCategoryObject="/Script/CoreUObject.ScriptStruct'/Script/CoreUObject.LinearColor'",PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,DefaultValue="(R=0.000000,G=0.660000,B=1.000000,A=1.000000)",AutogeneratedDefaultValue="(R=0.000000,G=0.660000,B=1.000000,A=1.000000)",PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=True,bOrphanedPin=False,) CustomProperties Pin (PinId=36CC9845469AFAC0024C4BA0A7778FFC,PinName="Duration",PinToolTip="Duration\nFloat (single-precision)\n\nThe display duration (if Print to Screen is True). Using negative number will result in loading the duration time from the config.",PinType.PinCategory="real",PinType.PinSubCategory="float",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,DefaultValue="5.000000",AutogeneratedDefaultValue="2.000000",PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=True,bOrphanedPin=False,) CustomProperties Pin (PinId=68DB72FB4E7C3A946F7FDAB9A2463273,PinName="Key",PinToolTip="Key\nName\n\nIf a non-empty key is provided, the message will replace any existing on-screen messages with the same key.",PinType.PinCategory="name",PinType.PinSubCategory="",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=True,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,DefaultValue="None",AutogeneratedDefaultValue="None",PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=True,bOrphanedPin=False,) End Object Begin Object Class=/Script/BlueprintGraph.K2Node_CallFunction Name="K2Node_CallFunction_4" ExportPath="/Script/BlueprintGraph.K2Node_CallFunction'/Game/ThirdPerson/Blueprints/BP_ThirdPersonCharacter.BP_ThirdPersonCharacter:EventGraph.K2Node_CallFunction_4'" FunctionReference=(MemberParent="/Script/CoreUObject.Class'/Script/Engine.KismetSystemLibrary'",MemberName="PrintString") NodePosX=1536 NodePosY=768 AdvancedPinDisplay=Hidden EnabledState=DevelopmentOnly NodeGuid=10B2C28148F30742A72220AFBC4189F4 CustomProperties Pin (PinId=4B794A1547001A751BB1E3A5D3FCB42F,PinName="execute",PinToolTip="\nExec",PinType.PinCategory="exec",PinType.PinSubCategory="",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,LinkedTo=(K2Node_IfThenElse_0 14F8E61C4470196AB44FE18C78F330F0,),PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,) CustomProperties Pin (PinId=7ACEFAF1451255C9198B5795DBAB32A7,PinName="then",PinToolTip="\nExec",Direction="EGPD_Output",PinType.PinCategory="exec",PinType.PinSubCategory="",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,) CustomProperties Pin (PinId=838863114339A301A55E2CAD059B8004,PinName="self",PinFriendlyName=NSLOCTEXT("K2Node", "Target", "Target"),PinToolTip="Target\nKismet System Library Object Reference",PinType.PinCategory="object",PinType.PinSubCategory="",PinType.PinSubCategoryObject="/Script/CoreUObject.Class'/Script/Engine.KismetSystemLibrary'",PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,DefaultObject="/Script/Engine.Default__KismetSystemLibrary",PersistentGuid=00000000000000000000000000000000,bHidden=True,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,) CustomProperties Pin (PinId=9452B9694B15C99EB963A7884AB1A100,PinName="WorldContextObject",PinToolTip="World Context Object\nObject Reference",PinType.PinCategory="object",PinType.PinSubCategory="",PinType.PinSubCategoryObject="/Script/CoreUObject.Class'/Script/CoreUObject.Object'",PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=True,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,PersistentGuid=00000000000000000000000000000000,bHidden=True,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,) CustomProperties Pin (PinId=B38E9FE14BEC997956E2DEB4FE0B04CD,PinName="InString",PinToolTip="In String\nString\n\nThe string to log out",PinType.PinCategory="string",PinType.PinSubCategory="",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,DefaultValue="Failure Connected to Host",AutogeneratedDefaultValue="Hello",PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,) CustomProperties Pin (PinId=FBF62C2E4C3F92866C1F0984702C11A0,PinName="bPrintToScreen",PinToolTip="Print to Screen\nBoolean\n\nWhether or not to print the output to the screen",PinType.PinCategory="bool",PinType.PinSubCategory="",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,DefaultValue="true",AutogeneratedDefaultValue="true",PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=True,bOrphanedPin=False,) CustomProperties Pin (PinId=3D54EE2F4AD386C6D7E5A0BEF67C118D,PinName="bPrintToLog",PinToolTip="Print to Log\nBoolean\n\nWhether or not to print the output to the log",PinType.PinCategory="bool",PinType.PinSubCategory="",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,DefaultValue="true",AutogeneratedDefaultValue="true",PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=True,bOrphanedPin=False,) CustomProperties Pin (PinId=742684EC4F183E06F47C78ACC4BF5CA4,PinName="TextColor",PinToolTip="Text Color\nLinear Color Structure\n\nThe color of the text to display",PinType.PinCategory="struct",PinType.PinSubCategory="",PinType.PinSubCategoryObject="/Script/CoreUObject.ScriptStruct'/Script/CoreUObject.LinearColor'",PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,DefaultValue="(R=0.000000,G=0.660000,B=1.000000,A=1.000000)",AutogeneratedDefaultValue="(R=0.000000,G=0.660000,B=1.000000,A=1.000000)",PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=True,bOrphanedPin=False,) CustomProperties Pin (PinId=780C2B564E0FCF7B81CADBBCBDF19B0C,PinName="Duration",PinToolTip="Duration\nFloat (single-precision)\n\nThe display duration (if Print to Screen is True). Using negative number will result in loading the duration time from the config.",PinType.PinCategory="real",PinType.PinSubCategory="float",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,DefaultValue="5.000000",AutogeneratedDefaultValue="2.000000",PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=True,bOrphanedPin=False,) CustomProperties Pin (PinId=E1E4607E47ADEADC05A535A4A502C74E,PinName="Key",PinToolTip="Key\nName\n\nIf a non-empty key is provided, the message will replace any existing on-screen messages with the same key.",PinType.PinCategory="name",PinType.PinSubCategory="",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=True,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,DefaultValue="None",AutogeneratedDefaultValue="None",PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=True,bOrphanedPin=False,) End Object Begin Object Class=/Script/BlueprintGraph.K2Node_CallFunction Name="K2Node_CallFunction_6" ExportPath="/Script/BlueprintGraph.K2Node_CallFunction'/Game/ThirdPerson/Blueprints/BP_ThirdPersonCharacter.BP_ThirdPersonCharacter:EventGraph.K2Node_CallFunction_6'" FunctionReference=(MemberName="PingEvent",MemberGuid=5BD80F5F4A8B9348E5367C9EE7DC3751,bSelfContext=True) NodePosX=352 NodePosY=384 NodeGuid=CEF65F4F4645FD40845184A972E34DC2 CustomProperties Pin (PinId=2C9B940A4D10AADA10399B9F60FF49B2,PinName="execute",PinToolTip="\nExec",PinType.PinCategory="exec",PinType.PinSubCategory="",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,LinkedTo=(K2Node_Event_0 9CB66600479CAAE192CD17823296C033,),PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,) CustomProperties Pin (PinId=D94EEE4346024C0C1917AFBE825B7D3A,PinName="then",PinToolTip="\nExec",Direction="EGPD_Output",PinType.PinCategory="exec",PinType.PinSubCategory="",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,) CustomProperties Pin (PinId=F463D0E341E915C09861B8A86B1F0686,PinName="self",PinFriendlyName=NSLOCTEXT("K2Node", "Target", "Target"),PinToolTip="Target\nSelf Object Reference",PinType.PinCategory="object",PinType.PinSubCategory="self",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,) End Object
Test Your Online Beacon Implementation
To test the implementation of your online beacon, you must run your project with either a dedicated or listen server and at least one standalone client. You do not need to connect your client to the server with the open
console command. This is a key feature of online beacons, clients can initiate contact with the server and then disconnect in a quick transaction.
To test your online beacon implementation:
-
Mare sure that you have compiled your project successfully.
-
Open your project in the Unreal Editor.
-
In the Editor Preferences, change the Level Editor > Play settings to the following:
-
Under Play in Standalone Game:
- Set Additional Launch Parameters to
-WINDOWED -ResX=800 -ResY=640 -log
.
- Set Additional Launch Parameters to
-
Under Multiplayer Options:
-
Enable Launch Separate Server.
-
Set Play Net Mode to Play Standalone.
-
Disable Run Under One Process.
-
Set Additional Server Launch Parameters to
-log
.
-
Click image to expand.
-
-
Click Play. You should see three new windows appear: a server log window, a client log window, and a client game instance.
-
If you see the following line in your client log window, the ping beacon has succeeded:
LogPingClient: Ping Complete: 29 ms
The actual ms count might vary.
Debugging
If you do not see the above line in your client log window, then the ping beacon likely did not succeed. If the ping beacon does not succeed, check the following.
Port
Make sure your client online beacon specifies the same port as the server online beacon in the engine configuration.
[/Script/OnlineSubsystemUtils.OnlineBeaconHost]
ListenPort=8888
Network Driver
Make sure your server created a network driver to listen on this specified port.
LogNet: IpNetDriver_1 IpNetDriver_1 IpNetDriver listening on port 8888
If you do not see a line similar to this in your log that specifies the same port as above, review the Engine Configuration section above.
Logging
Online Beacons use the LogBeacon
log category to log all online beacon network traffic. LogNet
and LogHandshake
are additional log categories that can be useful for debugging online beacons.
Resources
Ping Beacon Code
Ping Client
PingClient.h
#pragma once
#include "CoreMinimal.h"
#include "OnlineBeaconClient.h"
#include "PingClient.generated.h"
DECLARE_LOG_CATEGORY_EXTERN(LogPingClient, Log, All);
/**
*
*/
UCLASS(Blueprintable, BlueprintType, Transient, NotPlaceable, Config = Engine)
class BEACONS_API APingClient : public AOnlineBeaconClient
{
GENERATED_BODY()
public:
APingClient(const FObjectInitializer& ObjectInitializer);
virtual void OnFailure() override;
UFUNCTION(Client, Reliable)
void ClientPingBegin();
UFUNCTION(Server, Reliable, WithValidation)
void ServerPong();
UFUNCTION(Client, Reliable)
void ClientPingEnd();
UFUNCTION(BlueprintCallable, Category=Ping)
bool ConnectToHost(FString Address, int32 Port, const bool bPortOverride);
UFUNCTION(BlueprintCallable, Category=Ping)
void Disconnect();
protected:
int64 PingBeginTime;
int32 PingMS;
};
PingClient.cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "PingClient.h"
DEFINE_LOG_CATEGORY(LogPingClient)
APingClient::APingClient(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer)
{
}
void APingClient::OnFailure()
{
Super::OnFailure();
UE_LOG(LogPingClient, Log, TEXT("APingClient connection failed"))
}
void APingClient::ClientPingBegin_Implementation()
{
UE_LOG(LogPingClient, Log, TEXT("APingClient::ClientPingBegin_Implementation"));
PingBeginTime = FDateTime::Now().GetTicks();
ServerPong();
}
bool APingClient::ServerPong_Validate()
{
return true;
}
void APingClient::ServerPong_Implementation()
{
UE_LOG(LogPingClient, Log, TEXT("APingClient::ServerPong_Implementation"));
ClientPingEnd();
}
void APingClient::ClientPingEnd_Implementation()
{
UE_LOG(LogPingClient, Log, TEXT("APingClient::ClientPingEnd_Implementation"));
int64 PingTime = FDateTime::Now().GetTicks() - PingBeginTime;
PingMS = (int32)(PingTime / 10000);
UE_LOG(LogPingClient, Log, TEXT("Ping Complete: %d ms"), PingMS);
}
bool APingClient::ConnectToHost(FString Address, int32 Port, const bool bPortOverride)
{
FURL url(nullptr, *Address, ETravelType::TRAVEL_Absolute);
if (bPortOverride)
{
url.Port = Port;
}
else
{
int32 ListenPort;
if (GConfig->GetInt(TEXT("/Script/OnlineSubsystemUtils.OnlineBeaconHost"), TEXT("ListenPort"), ListenPort, GEngineIni))
{
url.Port = ListenPort;
}
else
{
url.Port = 8888;
}
}
return InitClient(url);
}
void APingClient::Disconnect()
{
DestroyBeacon();
}
Ping Host
PingHost.h
#pragma once
#include "CoreMinimal.h"
#include "OnlineBeaconHost.h"
#include "PingHost.generated.h"
DECLARE_LOG_CATEGORY_EXTERN(LogPingHost, Log, All);
/**
*
*/
UCLASS(Blueprintable, BlueprintType, Transient, NotPlaceable, Config=Engine)
class BEACONS_API APingHost : public AOnlineBeaconHost
{
GENERATED_BODY()
public:
APingHost(const FObjectInitializer& ObjectInitializer);
UFUNCTION(BlueprintCallable, Category=Ping)
bool InitializeHost();
UFUNCTION(BlueprintCallable, Category=Ping)
void RegisterHostObject(AOnlineBeaconHostObject* HostObject);
protected:
bool bInitSuccess;
};
PingHost.cpp
#include "PingHost.h"
DEFINE_LOG_CATEGORY(LogPingHost)
APingHost::APingHost(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer)
{
BeaconState = EBeaconState::AllowRequests;
}
bool APingHost::InitializeHost()
{
bInitSuccess = InitHost();
return bInitSuccess;
}
void APingHost::RegisterHostObject(AOnlineBeaconHostObject* HostObject)
{
if (bInitSuccess)
{
RegisterHost(HostObject);
}
}
Ping Host Object
PingHostObject.h
#pragma once
#include "CoreMinimal.h"
#include "OnlineBeaconHostObject.h"
#include "PingHostObject.generated.h"
DECLARE_LOG_CATEGORY_EXTERN(LogPingHostObject, Log, All);
/**
*
*/
UCLASS(Blueprintable, BlueprintType, Transient, NotPlaceable, Config = Engine)
class BEACONS_API APingHostObject : public AOnlineBeaconHostObject
{
GENERATED_BODY()
public:
APingHostObject(const FObjectInitializer& ObjectInitializer);
virtual AOnlineBeaconClient* SpawnBeaconActor(class UNetConnection* ClientConnection) override;
virtual void OnClientConnected(class AOnlineBeaconClient* ClientActor, class UNetConnection* ClientConnection) override;
virtual bool Init();
};
PingHostObject.cpp
#include "PingHostObject.h"
#include "PingClient.h"
DEFINE_LOG_CATEGORY(LogPingHostObject)
APingHostObject::APingHostObject(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer)
{
ClientBeaconActorClass = APingClient::StaticClass();
BeaconTypeName = ClientBeaconActorClass->GetName();
PrimaryActorTick.bCanEverTick = true;
PrimaryActorTick.bAllowTickOnDedicatedServer = true;
PrimaryActorTick.bStartWithTickEnabled = true;
}
AOnlineBeaconClient* APingHostObject::SpawnBeaconActor(UNetConnection* ClientConnection)
{
return Super::SpawnBeaconActor(ClientConnection);
}
void APingHostObject::OnClientConnected(AOnlineBeaconClient* ClientActor, UNetConnection* ClientConnection)
{
Super::OnClientConnected(ClientActor, ClientConnection);
APingClient* BeaconClient = Cast<APingClient>(ClientActor);
if (BeaconClient != nullptr)
{
BeaconClient->ClientPingBegin();
}
}
bool APingHostObject::Init()
{
return true;
}
Game Mode Code
BeaconsGameMode.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/GameModeBase.h"
#include "BeaconsGameMode.generated.h"
UCLASS(minimalapi)
class ABeaconsGameMode : public AGameModeBase
{
GENERATED_BODY()
public:
ABeaconsGameMode();
bool InitPingBeacon();
protected:
virtual void BeginPlay();
};
BeaconsGameMode.cpp
// Copyright Epic Games, Inc. All Rights Reserved.
#include "BeaconsGameMode.h"
#include "BeaconsCharacter.h"
#include "UObject/ConstructorHelpers.h"
#include "PingBeacon/PingHost.h"
#include "PingBeacon/PingHostObject.h"
ABeaconsGameMode::ABeaconsGameMode()
{
// set default pawn class to our Blueprinted character
static ConstructorHelpers::FClassFinder<APawn> PlayerPawnBPClass(TEXT("/Game/ThirdPerson/Blueprints/BP_ThirdPersonCharacter"));
if (PlayerPawnBPClass.Class != NULL)
{
DefaultPawnClass = PlayerPawnBPClass.Class;
}
}
bool ABeaconsGameMode::InitPingBeacon()
{
ENetMode Mode = GetNetMode();
if (Mode == NM_DedicatedServer || Mode == NM_ListenServer)
{
APingHost* Host = GetWorld()->SpawnActor<APingHost>(APingHost::StaticClass());
if (Host && Host->InitializeHost())
{
APingHostObject* HostObject = GetWorld()->SpawnActor<APingHostObject>(APingHostObject::StaticClass());
if (HostObject)
{
Host->RegisterHostObject(HostObject);
return true;
}
}
}
return false;
}
void ABeaconsGameMode::BeginPlay()
{
bool bSuccess = InitPingBeacon();
if (bSuccess)
{
UE_LOG(LogTemp, Log, TEXT("PingBeacon Init Success"))
}
else
{
UE_LOG(LogTemp, Log, TEXT("PingBeacon Init Failure"))
}
}