参考资料 Multiplayer in Unreal Engine: How to Understand Network Replication - YouTube [UE4/UE5][C++] 虚幻引擎框架或者虚幻运行原理 - 知乎 (zhihu.com) replicate的基本概念游戏服务器维护了绝对权威的世界状态。当游戏服务器的世界的状态改变,游戏服务器会把改变的状态传给每个客户端游戏的世界。这个过程称之为replicate(复制)。虚幻的复制系统让我们很容易开发出网络游戏,而不必去关注任何网络细节。你只要说我想要这个property replicate(复制)一下,然后它就可以被传输到客户端。 netmode(world的网络模式)netmode是world的property之一。 netmode包含以下4个重要成员,NM_Standalone, NM_DedicatedServer, NM_ClientSever, NM_Client。 关于netmode的灵魂三问这个游戏可以玩吗? 我们的gameinstance有一个localplayer吗?我们可以处理这个Player的input,并把世界渲染到viewport吗? 我们是一个服务器吗?换句话说,我们是否有最权威的世界副本,是否有gamemode这个actor?如果我们是服务器,我们是否对远程连接请求开放?其他的Player能加入,并扮演客户端? 这些问题的答案决定你的游戏的netmode。如下表格。 在我之前的一片文章中说过,engine的loadmap会去寻找一个url,这个url可以使本地的,也可以使远程的。 如果你的游戏已经连接了一个远程服务器,你的world就是NM_Client网络模式。所以你的world只能按照服务器的world来更新。 如果你的游戏本地加载世界,你的world就是NM_Standalone网络模式。因此你的游戏既是服务器也是客户端。你的游戏在本地运行,且不对任何外部请求开放。 但是如果你在本地运行,但是有监听选项,那么你的world就是listen sever网络模式。这个基本就是个NM_Standalone网络模式,但是别的本地游戏实例依然能作为客户端访问。 如果你的游戏实例是dedicate server网络模式,这个游戏实例既没有localplayer,也没有viewport。这只是一个服务器端的应用,玩家可以作为服务端连接。 虚幻复制系统基础为了让虚幻复制系统有效运行,这三个类非常重要。UNetDriver,UNetConnection,UChannel。 无论客户端还是服务器都有GameEngine,而每个GameEngine都有自己的GameNetDriver。当server启动时,gameengine创建UNetDriver,UNetDriver开始监听远程连接请求。当客户端启动时,game engine同样创建UNetDriver,UNetDriver开始向服务器发送连接请求。一旦连接建立,server就会建立一个UNetConnection来维护连接。server会为每个客户端游戏建立一个UNetConnection。但是客户端只有一个UNetConnection来维护自己与服务器的连接。 每个UnetConnection有非常多的Channel,VoiceChannel,ActorChannel。 actor同步如果你需要一个actor通过网络保持连接,你就需要设置bReplicates为TRUE。然后用IsNotRelevantFor来检测这个actor属于哪个player,然后通过netconnection中的actorchannel来交换信息。 如果服务器生成了一个actor,然后服务器会通知client要复制自己的actor。如果这个actor在服务器上被删除,客户端同样也会被删除。同样的,每个actor可能也有replicated properties, 这个property给我的感觉就是成员变量。如果actor的property被标记了replicated,那么如果服务器上的property改变,客户端的property也会随之改变。 例子在你自定义的actor比如weapon设置bReplicates = true,这个bReplicates = true,就意味着如果服务器创建了这个weapon,那么这个actor就会把这个weapon副本给客户端。
在使用这个weapon的Character类里,设置UPROPERTY(ReplicatedUsing=OnRepXXX)。并重写GetLifetimeReplicatedProps。被标注的OverlappingWeapon在服务器如果发生改变,服务器就会传给客户端。但是on_RepXXX这里只会在客户端执行。On_RepXXX实际上是一个接收到服务器replicate后需要执行的函数,replicate过程是单向的,所以On_RepXXX只能再客户端执行。
实现GetLifetimeReplicatedProps,这里也是设置replicate条件的地方。
这里的OverlappingWeapon是一个指针,当它从null变为不是null的时候,就会触发客户端执行OnRep_OverlappingWeapon这个函数。UMG永远不会同步,Do you also play as a client when using listen server? - Programming & Scripting / Blueprint - Epic Developer Community Forums (unrealengine.com)。 如何在蓝图设置replicated?Property Replication | Unreal Engine Documentation ownership(所有权)所有权对于actor的replication也很重要。但是ownership同样可以在runtime时设置。 playerController的ownershipplayerController的所有权很重要。基本上,每个网络连接都代表着一个player。一旦这个player完全进入游戏,那个这个网络连接同样和playerController相连接。从服务器的角度来说,这个网络连接拥有这个playerController。除此之外,这个网络连接可以拥有这个playerController所拥有的所有actor。打个比方,如果你的游戏一个人物扔了个手榴弹,服务器可以追踪到这个手榴弹是你游戏人物扔的,并复制给其他所有的玩家。 相关性并不是所有的actor都需要复制给每个客户端。所以我们这里需要设置相关性。但是有的actor就是对于所有的客户端都复制。比如下面这个。 但是有些actor只对于一个客户端有相关性,所以这个actor只会复制给这个客户端。比如PlayerController这个actor只对自己的客户端有相关性,也只会复制给自己的客户端。 相关性还能被网络距离决定,如果一个actor没有设置相关性,但是如果你离一个actor过“近”的化,它也是和你有相关性。 更新频率和优先级更新频率和优先级直接决定了服务器给相关客户端发送更新的频率。NetUpdateFrequency直接决定了服务器要多久check一下客户端的actor,并给他发送新的更新数据。但是网络延迟和网络带宽同样也是重要影响因素,所以玩游戏时常常会卡成ppt。服务器的netdriver会根据网络带宽和actor的优先级来决定放弃哪些数据的传播。优先级并不是固定的,比如离服务器近的actor就会有高优先级,很长时间没有更新的就有高优先级。但是同样的,你也可以手动设置这些actor的优先级。 RPC (remote procedure calls)如果你把一个方法设计为多播。当你在服务器上调用一个函数时,服务器将要发送信息让每个客户端调用同样的方法。多播RPC不能用于复制永久数据给所有客户端。 可靠RPC和不可靠RPC这个就是TCP和UDP的区别。 RPC代码编写RPCs | Unreal Engine Documentation 这个大致过程就是,我的客户端在服务器上的地图捡到一个武器,但是捡到这个武器,并赋与客户端玩家这个函数需要在服务器上执行。在捡到武器的时候,客户端向服务器发送一个rpc请求,让服务器执行这个函数。在上面那个actor同步例子中,我们把weapon的bReplicate设置为了true,说明了这个weapon只能由服务器创建,然后replicate给客户端,所以当我们捡到这个武器时,事实上是在服务器上执行了将这个武器的owner设置为我的客户端,并replicate其他客户端。注意这个函数实现的命名形式,加了一个Implementation。
Replicated Properties vs RPCsreplicated properties同样和网络相关。尽管replicated properties可能发生延时,比如和你的pawn相关性没有了,但是一旦条件达成,最终会把property复制给你的pawn。可参见视频里的例子,那个例子视频里举得很好。 Local role和Remote role这个代码时获取local role和remote role
Standalone local这个是在standalone模式下,本地机器对这个可爱的小人的权限。这里拥有绝对的权限。
|Archiver|手机版|小黑屋|软件开发编程门户 ( 陇ICP备2024013992号-1|甘公网安备62090002000130号 ) GMT+8, 2024-11-21 14:20 , Processed in 0.034856 second(s), 16 queries . Powered by Discuz! X3.5 © 2001-2024 Discuz! Team. |