UE4 | Inventory for Multiplayer # 5 | Transfer of information between the Server and the Customer

The list of articles [/b]
UE4 | Inventory for Multiplayer # 1 | Data warehouse on the DataAsset
 
UE4 | Inventory for Multiplayer # 2 | Connecting Blueprint to C ++
 
UE4 | Inventory for Multiplayer # 3 | The structure of the interaction is
 
UE4 | Inventory for Multiplayer # 4 | Creation and connection of the coneer
 
UE4 | Inventory for Multiplayer # 5 | Transfer of information between the Server and the Customer
 
UE4 | Inventory for Multiplayer # 5 | Transfer of information between the Server and the Customer In this article we will consider the transfer of data between the Server and the Client in
Unreal Engine 4
implemented on
C ++
. At the very beginning, for a person who does not have a specialized education, this seems something incomprehensibly complex. Despite a large number of examples and parsing, personally it was very difficult for me to add a holistic picture of this process. But, when the critical volume of the information obtained and the tests that were taken was reached, it became clear how this works. here .
 
With the replication of variables, everything is somewhat more interesting.
 
Let's start with the header file
.h
.
 
You can simply replicate the variable:
 
UPROPERTY (Replicated)
bool bMyReplicatedVariable;

 
And you can run some function on the client side if the variable was replicated. It does not matter what values ​​the variable took. The very fact of its change is important.
 
UPROPERTY (ReplicatedUsing = OnRep_MySomeFunction)
TArray
MyReplicatedArray;
UFUNCTION ()
void OnRep_MySomeFunction ();

 
Running a function is nothing more than one way to transfer commands from the Server. It is very important to know that replication of arrays does not take place entirely, but only the changed part. Thus, with just one variable, you can transfer a lot of commands from the server, sorting the array into elements, and elements to bits.
 
Now go to
. cpp
 
We prescribe the replication conditions:
 
void AMySuperActor :: GetLifetimeReplicatedProps (TArray
& OutLifetimeProps) const
{
Super :: GetLifetimeReplicatedProps (OutLifetimeProps);
DOREPLIFETIME (AMySuperActor, bMyReplicatedVariable);
DOREPLIFETIME_CONDITION (AMySuperActor, MyReplicatedArray, COND_OwnerOnly);
}

 
The first variable is
bMyReplicatedVariable
was replicated without any condition at once to all Clients, whereas the second,
MyReplicatedArray
, was updated only for the client of the owner of the object
AMySuperActor
, if, of course, it was declared.
 
A complete list of possible conditions can be found here .
 
 
RPC ( ? Remote Procedure Calls
)
 
This method of data transfer, unlike replication works in both directions, but is more expensive. To use it, you also need to connect
#include "UnrealNetwork.h"
.
 
 
An important feature is the
method.
RPC
you can pass variables.
 
 
First you need to say that RPCs come with a confirmation of receiving parcel
Reliable
and without it
Unreliable
. If in the first case the Sender does not rest until he is satisfied that the parcel is delivered (and will send it again and again, if there is no reply message), then in the second, the Sender absolutely does not care if someone received his package or not. I sent and forgot.
 
Where possible, we use
Unreliable
. Typically, this method is suitable for not very important information, or for frequently updated data. Where it is impossible, in the case of sending from the Server to the Client, we try to do replication with the function call, as it was shown above.
 
So, to send our package from the Client to the Server, you need to register three functions:
 
UFUNCTION (Reliable, Server, WithValidation)
void ServerTestFunction (float MyVariable);
void ServerTestFunction_Implementation (float MyVariable);
bool ServerTestFunction_Validate (float MyVariable);

 
Reliable
- sending with confirmation of receipt.
 
Server
- sending from the Client to the Server.
 
WithValidation
- the package is opened by the receiver only if the conditions described in the function
are observed. bool ServerTestFunction_Validate (float MyVariable)
. That is, if the function returns
true
.
 
ServerTestFunction (float MyVariable)
- this function is called by the client, if he wants, to send something to the server. In general, it is not even necessary to describe it in
. cpp
.
 
ServerTestFunction_Implementation (float MyVariable)
- this function will be called directly on the Server only if
 
ServerTestFunction_Validate (float MyVariable)
- this function is performed on the Server, and if
is returned. true
, then
is called. ServerTestFunction_Implementation (float MyVariable)
.
 
To send a parcel from the Server to the Client, if we are not completely satisfied with the use of replication, only
actually changes. Server
on
Client
:
 
UFUNCTION (Reliable, Client, WithValidation)
 
The names of functions, in principle, can be any, but usually they should reflect where the parcel is going. For our own convenience.
 
UFUNCTION (Reliable, Client, WithValidation)
void ClientTestFunction (float MyVariable);
void ClientTestFunction_Implementation (float MyVariable);
bool ClientTestFunction_Validate (float MyVariable);

 
Otherwise, it works exactly the same as in the previous example, taking into account that this time the premise comes from the Server to the Client.
 
There is one more option for sending from the Server, when the parcel leaves at once to all customers.
 
UFUNCTION (Reliable, NetMulticast, WithValidation)
void NetMulticastTestFunction ();
void NetMulticastTestFunction_Implementation ();
bool NetMulticastTestFunction_Validate ();

 
Do not abuse this option. Think, maybe you will get by with replication.
 
 
Example of the implementation of the request to the Server [/b]
/* This function can be executed both on the Client and on the Server * /
void ADreampaxActor :: DoSomethingWithOtherActor (ADreampaxOtherActor * SomeOtherActor)
{
/* perform a check if the function is running on the Client * /
if (Role < ROLE_Authority)
{
/* send a command to the server, with a pointer to the object,
.Which we want to perform the action * /
) ServerDoSomethingWithOtherActor (SomeOtherActor);
/* abort the function,
it is on the client * /
return;
}
/* get here only if the function is running on the server * /
SomeOtherActor-> Destroy (true);
}
.
/* This function is always started on Server,
if ServerDoSomethingWithOtherActor (SomeOtherActor)
is enabled and the validation condition has been passed * /
void ADreampaxCharacter :: ServerDo SomethingWithOtherActor_Implementation (ADreampaxOtherActor * SomeOtherActor)
{
/* We launch the function, but it is already guaranteed on the server side * /
DoSomethingWithOtherActor (SomeOtherActor);
}
.
/* checking the condition on the Server side, can I run
ServerDoSomethingWithOtherActor_Implementation (ADreampaxOtherActor * SomeOtherActor) * /
bool ADreampaxCharacter :: ServerDoSomethingWithOtherActor_Validate (ADreampaxOtherActor * SomeOtherActor)
{
/* in this casealways return true,
but if necessary, we can check something
and return fasle. Then the function on the server will not start * /
return true;
}

 
That's all you need to know about communication between the Server and the Client to go to the next section, where we'll list the replication of the inventory and see how to correctly make changes to it.
 
P.S. If you notice any inaccuracies or errors, please write in the comments.
+ 0 -

Add comment