ue4 rpc php,UE4 服务器RPC模式,Role角色解疑

Overview

Unreal's network replication is extremely fast and bandwidth efficient.

The networking model is authoritative server/client.

Character and Vehicle based motion, physics, and prediction "just work" out of the box.

Unreal will replicate properties, structs, and references to other objects automatically over the network.

You can call functions on objects "across the network" (Remote Procedure Calls).

Like many parts of Unreal if you use it enough it may begin excite you in ways that some people will find socially unacceptable. Just remember that the UE4 community is here for you. Trust us when we say we understand how you feel and that a change of underwear might be in order.

TerminologyObjects, Game Objects, Actors, Pawns, Characters - These are all UObject derived classes.

Server - The computer process with an instance of a UWorld that contains Actors that are replicated to clients. The state of the world contained here is considered to be the "real" or "correct" one.

Client - The computer process with an instance of a UWorld that contains Actors that were received from a Server over a network connection. The state of a client is an approximation of the state of the Server. It is not considered to be accurate or correct.

Concepts

At a high level Unreal's networking is designed to efficiently transmit (replicate) all relevant AActors contained in a UWorld from the authoritative state contained in a server to all of its connected clients. Unreal's networking is considered to be what's called "Authoritative Server/Client" because the state of the world contained in the server process is considered to be the true state of the world, while at any given time the state of the world on a client will, at best, approximate that to some degree of precision.

Although not without their downsides authoritative networking models, in theory, are immune to cheating. If done correctly, the entire state of the world is simulated on the server with clients restricted to issuing "input" to the server (conceptually: move forward, backwards, left, right, switch weapons) making it impossible for clients to "spoof" game state like their velocity because client calculations about their motion and velocity are entirely meaningless and never leave the clients computer. Instead clients receive the results of their "input" to the server at some later time.

[在高级别上虚幻的网络是为了有效地传输(复制)在UWorld里包含的所有的AActors,从权威状态服务器中包含到所有连接的客户端。 虚幻的网络被认为是所谓的“权威服务器/客户端”,因为世界包含在服务器进程的状态被认为是世界的真实状态,而在任何给定的时间世界客户的状态,在最好的情况下,近似,在一定程度上的精度。

虽然权威网络模型不是没有缺点,从理论上讲,不受欺骗。 如果能够做得正确使整个世界是模拟的状态以及客户端在服务器限制发行“输入”服务器(概念上:向前,向后,左,右,切换武器)使得客户“恶搞”游戏状态例如改变他们的速度, 事实上,客户对他们的运动和速度计算完全是无意义的,并且从来没有脱离客户端计算。反而,客户端应该是接收服务器端最新的输入结果]

A Guide To Network Roles

A key concept to understand Unreal's networking is the concept of a network role. Although not totally obvious at first, networking roles are really the rules that control how information flows between Server and Client. For the most part Unreal's networking is automatic and hidden out of sight: simply changing the value of a member on a field on the Server may cause that new value to be replicated to clients. Why and how that happens is because of the rules governing network roles.

Spawning Rule

The first rule of networking in Unreal is that only servers can spawn Actors that will replicate to clients. If a client spawns an Actor that actor will only ever exist on the client that created it.

UPROPERTY Replication Rule

Only the changes made to replicated properties in the server will be replicated to clients. If a client changes the value of a replicated variable locally then it will stay that way until the next time the server changes it (after which it will be replicated and overwritten on the client). In this sense you should consider a UPROPERTY that is tagged with Replicated to be owned/controlled by the server.

Rules For Calling Functions

One of the most powerful features of Unreal networking is the ability to call functions on objects on the server version or client version of objects. Consider an example of a game with a server and two clients and a single actor in the world. In this example there are 3 copies of the actor, one on the server, and one on each client. Let's call them Actor_Server, Actor_Client1, Actor_Client2.

At this point we must now start talking about network roles. There are four roles (* see technical note below):

ROLE_None【最佳垃圾者,我只能干自己的事,网络关我屁事】

The object has no networking role and isn't replicated.

ROLE_SimulatedProxy【最佳模拟者,我不管网络的事,但他妈的管我,我只是个客户端垃圾狗】——[我只能接受服务器给我发送的命令]

The object locally simulates the state of the object on the server (i.e. it tries to look and act like the server version). It has no authority to change the state of the object or call a function on the object that executes remotely.

ROLE_AutonomousProxy【最佳模拟者,网络和我有点关系,就算我可以管你,但我还是个客户端垃圾狗】——[我可以接受也可以向服务器发送命令]

Identical to ROLE_SimulatedProxy in that this object also locally simulates the state of the object on the server, but with the ability to execute function calls on this object that execute on the server. In this sense an object with ROLE_AutomousProxy is allowed to make authoritative decisions over what the Actor does, by executing functions on the object that run on the server and therefore change its state.

The choice of what functions can be replicated on the server are critical in preventing cheating. For example, a replicated function that runs on the server which takes the position of an object and moves it to that location is potentially a vector for cheating, since a player could modify their code to call that function with any values they desired. A more secure design would be to have server replicated functions transmit high level commands like ServerMoveForward(), ServerMoveBackwards(), ServerFireWeapon() etc.

[与ROLE_SimulatedProxy相同也在这个对象在本地模拟服务器上的对象的状态,但有能力执行函数调用这个对象在服务器上执行。 在这个意义上,一个ROLE_AutomousProxy对象允许权威决策这个对象做什么,通过在服务器上运行执行函数对象去改变其状态。

选择什么函数可以被复制在服务器上是至关重要的在防止作弊方面。 例如,一个复制函数运行在服务器上,获得一个物体的位置并且移动它,位置对于作弊是一个潜在的向量,因为一个角色可以修改他们的代码调用函数与他们想要的任何值。 更安全的设计是有服务器复制函数传递高层命令:ServerMoveForward(),ServerMoveBackwards(),ServerFireWeapon()等。]

ROLE_Authority【老子最牛逼,网络就是我,我就是网络,我是神】

An object with ROLE_Authority is the authoritative version of the object and its state represents what is considered to be the only "real" state of the object. Versions of this object on clients with ROLE_AutonomousProxy can call functions on this version of the object.[ROLE_Authority的类型是这个对象的权威版本并且他的状态代表了被认为是唯一的“真正的”对象的状态。 这个对象的版本会是ROLE_AutonomousProxy的类型存在于客户端去调用函数在这个版本的对象。]

An object with ROLE_Authority can execute function calls on any object on the server. Those functions can be marked to replicate to clients and they will be executed on the ROLE_SimulatedProxy and ROLE_AutonomousProxy instances of those objects on the specified clients.[ROLE_Authority类型可以在任何对象执行函数在服务器上。 这些调用都可以复制给客户,这些调用被执行在ROLE_SimulatedProxy和ROLE_AutonomousProxy实例指定的客户端]

Finally an object with ROLE_Authority will also replicate any changes to UPROPERTY fields to any client versions of the object.

In the example above with Actor_Server, Actor_Client1, and Actor_Client2, the likely networking role allocation would be:

Actor_Server - ROLE_Authority

Actor_Client1 - ROLE_AutonomousProxy (if the actor is a PlayerController and Client1 controls that player) or ROLE_SimulatedProxy

Actor_Client2 - ROLE_AutonomousProxy (if the actor is a PlayerController and Client2 controls that player) or ROLE_SimulatedProxy

Actor_Server:

Will have role ROLE_Authority and changes to any UPROPERTY on the Actor_Server instance will get replicated to both Actor_Client1 and Actor_Client2 automatically, and any UFUNCTION() methods that are replicated as Client or NetMulticast that are called on Actor_Server by the server will execute on Client1 (in the case of Client) or both Client1 and Client2 in the case of NetMulticast.

Actor_Client1:

For the sake of argument assuming Client1 owns the Actor then Client1 will have network role ROLE_AutonomousProxy, and any calls to UFUNCTION() methods marked as Server will execute on Actor_Server.

Actor_Client2 (and any other clients):

Will have role ROLE_SimulatedProxy (assuming as said before that Client1 owns the actor) and any calls to replicated functions will be ignore. This object can only receive replicated information in the form of property updates and function calls.[这个对象只能接收复制信息的形式属性更新和函数调用。]

*TECHNICAL NOTE:

You should be aware that Unreal does not necessarily enforce "rules" regarding networking roles, and roles don't really have privileges or authority over objects. Rather, roles serve as a way for you to know how an object should behave with respect to the network, and roles are assigned in a way that reflects the architecture of UE4 networking. For example technically a ROLE_SimulatedProxy object can invoke a Server RPC if it is owned by a PlayerController (or if it is a child of a PlayerController through a hierarchy of objects). In unmodified Unreal an Actor can invoke a Server RPC if there is a UNetConnection (i.e. a Player) in its owner hierarchy, therefore ONLY a Player or an object owned by a Player or its children (PlayerController, etc) can invoke a Server RPC.

[你应该知道虚幻关于网络角色不一定执行“规则”, 和角色没有特权或权力对象。 相反,角色服务作为一种方式让你知道一个对象如何应表现出尊重网络, 和角色分配的方式反映了UE4网络的体系结构。 例如ROLE_SimulatedProxy对象可以调用服务器RPC,如果它是属于PlayerController (或者如果它是PlayerController 的一个child 在对象的层次结构)。 在修改的不真实的Actor可以调用服务器RPC如果在它拥有者的层次结构中有UNetConnection (即一个球员), 因此只要Player 或一个对象的拥有者是Player 或是它的child (PlayerController)就可以调用服务器RPC。]

Basic Actor Replication

Any object derived from AActor can be a candidate for network replication by setting bReplicates to true inside your constructor:

ReplicatedActor.h:

#pragma once #include "Core.h" #include "AReplicatedActor.generated.h"   UCLASS() class AReplicatedActor : public AActor { GENERATED_UCLASS_BODY() };

ReplicatedActor.cpp:

AReplicatedActor::AReplicatedActor(const class FPostConstructInitializeProperties& PCIP) : Super(PCIP) { bReplicates = true; }

When Is An Actor Replicated?

An Actor is replicated to a client when it is considered to be "network relevant". There are a number of ways to control this. By default Unreal replicates an Actor when it is within range of a client (AActor::NetCullDistanceSquared controls the culling distance). Here are a list of the base AActor flags you can set in your constructor to control some basic relevancy semantics:

bReplicates : Must be true for an Actor to replicate anything. An actor that is spawned dynamically on a server will be replicated (and spawn) on Client ONLY if this flag is set.[需要网络复制必须]

bAlwaysRelevant : Actor is always relevant to all clients and will always be replicated.[时常复制]

bOnlyRelevantToOwner : Actor is only relevant to its owner. Unreal's concept of ownership for network relevancy purposes is limited to a players APlayerController or a players APawn. An actors owner must be either a PlayerController or Pawn controlled by a PlayerController in order for bOnlyRelevantToOwner to function. When set it means that the actor will only replicate to the player represented by the owning Pawn or PlayerController.[只会复制给他本地端,也就是OwnerClient]

bNetLoadOnClient : If true the Actor will load from a level file on a network client. This should be set to true for Actors you place in a map that you want to exist on a client (typically most Actors want this).[如果为true,Actor将会从level文件里加载到网络客户端。对于放在Map的Actors你希望它会存在于客户端(基本上都会有这个需求),那么这个就必须设置为True]

bTearOff : If the Server sets this to true all clients will take authoritative control of their locally replicated versions of the actor and changes and function calls on the actor will no longer be replicated over the network. It will be as though it was a locally spawned actor.[如果服务器设置,这样所有客户将权威控制他们的本地复制版本的演员和变化和函数调用的演员将不再是通过网络复制。 就好像它是一个本地产生的演员。]

bReplicateMovement : Set to true if you want to be able to move the Actor and have its position be updated on clients automatically. Pawns have this on by default.

If the default network relevancy by distance isn't adequate you can customize relevancy per-player by implementing an override for AActor::IsNetRelevantFor():[如果你希望能够将Actor的移动和他的方位被自动更新到所有的客户端就必须设置True,Pawns这个是默认设置为True。如果默认网络的相关性设定是依靠距离,在没有达到这个距离时,你可以通过实现一个自定义相关性每个玩家覆盖AActor::IsNetRelevantFor():]

bool AActor::IsNetRelevantFor(const AActor* RealViewer, const AActor* ViewTarget, const FVector& SrcLocation)

Actor Property Replication

Unreal will automatically replicate any UPROPERTY declared properties by declaring that they are Replicated and implementing UObject::GetLifetimeReplicatedProps(). Warning: It is vitally important that you do not conditionally replicate values inside GetLifetimeReplicatedProps (i.e. do not use any of your objects instance state to conditionally wrap DOREPLIFETIME). Doing this will not do what you think (internally Unreal only ever calls GetLifetimeReplicatedProps() on the first instance of an object of a given class and it expects to be given the replication layout for that class, not for an instance of that class. That replication layout is shared by all instances of that class for the lifetime of the UNetDriver).

void AReplicatedActor::GetLifetimeReplicatedProps(TArray< FLifetimeProperty > & OutLifetimeProps) const { DOREPLIFETIME(AReplicatedActor, bFlag); DOREPLIFETIME(AReplicatedActor, IntegerArray); }

Getting An Event When Your Property Is Replicated

Function Call Replication

One of the most powerful features of Unreal networking is the ability to call functions remotely. Any UFUNCTION() decorated method can be set to replicate and execute on client or server instances of the object. It is important to understand networking roles because they define the semantics by which remote function calls work.

Types of remote function calls

Server - The function will execute on the server version of the object ONLY. An object must have ROLE_Authority or ROLE_AutonomousProxy to execute this method. An object with any other networking role won't do anything. NOTE: Functions marked as Server must also be marked as WithValidation and implement a validate function. This lets you do cheat prevention if desired, otherwise an empty method that just returns true is typical.

Client - The function will execute on the client that has a version of the object with ROLE_AutonomousProxy (which is another way of saying whatever Client has a version of this object is allowed to call Server methods on the object, and is typically known as the client that "Owns" this object). The only ROLE_AutonomousProxy objects that exist in Unreal are client instances of PlayerControllers.

NetMulticast - The function will execute on all clients that have an instance of the object. Only an object with ROLE_Authority can execute this function, any other networking role won't do anything.

Quick Review Of Roles

ROLE_Authority - An object with ROLE_Authority (HasAuthority() will return true) is considered the authoritative state of an object. When it calls UFUNCTION() decorated methods that are marked to execute as Server, Client, or Multicast those functions will be replicated accordinly.

ROLE_AutonomousProxy - An object with this role can call UFUNCTION() decorated methods that are marked as Server.

An object with a role other than ROLE_Authority or ROLE_AutonomousProxy cannot call replicated methods (if they do they will be ignored).

Reliable vs Unreliable Function Call Replication

A replicated UFUNCTION() can replicate reliably or unreliably. This simply means that an unreliable method call may not be executed under severe network stress. Don't mark things as unreliable that have to happen, but this is a good idea to do for non-critical effects since it theoretically might make the game play better under network stress.

Remote Function Call Examples

ReplicatedActor.h

#pragma once #include "Core.h" #include "ReplicatedActor.generated.h"   UCLASS() class AReplicatedActor : public AActor { GENERATED_UCLASS_BODY()   public:   // NOTE: all functions can have arguments, they will be replicated automatically over the network. // NOTE: UObject based classes (or derivatives) should be passed by pointer (*) and will correctly // address the version of that object on the receiving client or server (unless that object is not // replicated, in which case the pointer will be NULL).   UFUNCTION(Server, Reliable, WithValidation) void Server_ReliableFunctionCallThatRunsOnServer();   UFUNCTION(Client, Reliable) void Client_ReliableFunctionCallThatRunsOnOwningClientOnly();   UFUNCTION(NetMulticast, Unreliable) void Client_UnreliableFunctionCallThatRunsOnAllClients(); };

ReplicatedActor.cpp:

#include "ReplicatedActor.h" #include "UnrealNetwork.h" AReplicatedActor::AReplicatedActor(const class FPostConstructInitializeProperties& PCIP) : Super(PCIP) { bReplicates = true; }   void AReplicatedActor::Server_ReliableFunctionCallThatRunsOnServer_Implementation() { // Do something here that modifies game state. }   bool AReplicatedActor::Server_ReliableFunctionCallThatRunsOnServer_Validate() { // Optionally validate the request and return false if the function should not be run. return true; }   void AReplicatedActor::Client_ReliableFunctionCallThatRunsOnOwningClientOnly() { // Do something here to affect the client. This method was called by the server ONLY. }   void AReplicatedActor::Client_UnreliableFunctionCallThatRunsOnAllClients_Implementation() { // Do something here to affect the client. This method was called by the server ONLY. }

Tips For Bandwidth and Robustness

There is a lot of flexibility when it comes to what you replicate and how you replicate it.

When possible use an event concept to replicate lots of state to clients with a single replicated method call. For example, instead of setting replicated properties and calling multiple functions to tell a client to set the position of an effect, spawn an explosion, and then play a sound (conceptually three different things) you can encapsulate all of this as one method call: Client_ProcessExplosion(const FVector& Location) that can be written to spawn explosion actors locally.

Going along with the previous tip, don't replicate objects that don't need to be. Explosions, sounds, ragdolls, and particle effects don't need to be marked as replicated, instead have a single replicated method that tells clients to Spawn() those Actors locally since they don't modify game state when an event happens.

Use Unreal's concepts of network roles to your advantage. This usually means only your players PlayerController can call Server functions. Be careful about what you send. Instead of letting a player tell the server their position explicitly, consider having the PlayerController send player commands (like move left, up, down) and simulate that state on both client and server and let the server update the players position as a replicated property. This avoid an entire class of cheats (like speed hacks etc).

Remember all replicated properties are sent reliably.

Replication of Actor Components and Subobjects

The Actor class provides built-in support for replicating components (classes derived from UActorComponent). If you want a component on your actor to replicate you should call SetReplicates(true) on the specific component in your class constructor after calling PCIP.CreateDefaultSubobject() to create the component.

Advanced: Generic replication of Actor Subobjects

Unreal can also replicate arbitrary UObject's that you have in your actor and it's surprisingly easy to do so:

First create the object class that you want to replicate over the network. It should override UObject::IsSupportedForNetworking(). Just like any normal object it should also contain some replicated properties or functions, and implement GetLifetimeReplicatedProps():

Actor Code For Subobject Support

On the Actor side we need to implement AActor::ReplicateSubobjects() and if we want to, we can store our custom object in a UPROPERTY just like any other object! The only "gotcha" here is that the object must be contained within the Actor (i.e. when it is constructed the new objects Outer must be the Actor).

Notes

As if by magic, on clients their Subobject UPROPERTY will contain a valid pointer to the newly replicated object after it is received from the server. The UObject derived class can contain replicated functions and properties just like any other object (and can implement GetLifetimeReplicatedProps)

Detailed Explanation

There is some awesomeness that is going on here that is worth peeking into to get an idea of the wizardry at work here.

Unreal networking is built around a few key classes and concepts. The first is an ActorChannel which is the connection to the server or client for transmitting data about the replication of an actor. The next piece is an FRepLayout contained inside the NetDriver. When Unreal calls your GetLifetimeReplicatedProps it does so only on the first replicated object of an instance of a specific UClass! The call to GetLifetimeReplicatedProps populates an FRepLayout object with the specific member fields that must be replicated for a particular UClass. This is why it's important not to have any conditionals in your GetLifetimeReplicatedProps that are based on object state.

Another part of the puzzle here is network GUIDs. Unreal generates a GUID for an instance of an object and stores objects in a replication map based on GUID. Objects are sent with a GUID identifier over the network. When Unreal replicates the value of a UPROPERTY that is a UObject* it is really replicating the GUID of that object, not the pointer address.

So what's happening here is that Unreal replicates your actor and then your subobject over the wire. On the client side they are received and your subobject is constructed with the replicated data. Then your actor property is received with the guid of your newly constructed subobject and the property is filled in with the address of your subobject. Neat!

Unreal's Type System

The real magic that happens with Unreal's network replication is enabled because it is able to generate reflection meta-data for all of your objects which allows them to get the types and sizes of the fields you want replicated as if by "magic".

Unreal's type system is built from a custom C++ pre-processor (the UnrealHeaderTool) which scans your C++ codebase and generates reflection meta-data. For those uninitiated in the concept of language reflection (a feature common in C# and Java) it is the ability for code written in a language to perform "introspection" on itself and other types. This means that you can write code that programmatically discovers types, functions, function-parameters, variables, properties and other meta-data. This is not the same as polymorphism. Polymorphism depends on the compiler knowing what the base-type is at compile time (i.e. statically). With reflection your code never has to know anything about the types it is working with at compile time.[真正的魔法发生在虚幻的网络复制启用的时候, 因为它是能够对你所有的对象产生反射的元数据, 通过这个魔法使他们能够得到想要的字段类型和大小。

虚幻的类型系统编译来自于是由一个定制c++预处理器(UnrealHeaderTool)去扫描你的c++代码库并且去反射元数据。 对于那些不知情语言反射(c#和Java)的概念中常见的一个特性是它能够在代码语言阶段去执行“内省”本身和其他类型。 这意味着您可以通过编程方式编写代码,发现类型,函数,函数参数、变量、属性和其他元数据。 这是不一样的多态性。 多态性取决于编译器在编译时知道基类型是什么(即静态)。 对于反射你的代码是不需要知道任何关于它的类型,因为这些工作都会在编译的时候去执行。

注:也就是在编译阶段,执行发射,可以得到类型,函数,参数,以及变量,属性和其他的元数据,类似预编译。这样去完成反射!]

有帮助就分享一下吧!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值