UE4网络功能相关笔记

RepNotity的作用

把变量设置成RepNotify除了像C#语言中的"属性"一样,提供一个改变变量时调用一个函数的机会以外,其真正重要的作用其实是应对网通同步延迟问题

一定要牢记网络同步是需要时间的,不像单机编程一样,程序的执行是同步的,即时的。

每个设置成“replicated"的属性的同步,以及RPC都是需要时间的,即使是局域网,即使是同一台机器上多个客户端,相互直接通信都是需要时间的-虽然时间很短,但也需要考虑到。

假设一个情形:某客户端的某个属性P变化以后,要让服务器执行某个函数F(这个函数需要用到属性P作为参数)。

错误的做法是在改变属性P之后立即执行服务器的函数F,因为一般情况下,P都不可能立即同步到服务器,那么函数F调用的P是较老的,未更新的数值。

正确的做法是将该属性设置成RepNotify,在自动生成的OnRep_P函数中调用函数F,这样做可以保证这个函数F是在属性P同步到服务器之后才执行。

客户端连接后都发生了什么?

情形:服务端先开启并创建Session,客户端开启并寻找Session,找到之后进行连接。

实验如图所示:

UE4网络功能相关笔记

经过这个实验,至少摸清楚了以下几个过程(覆盖并不是很全,只保证这些步骤的相对时间顺序是正确的):

服务端和客户端相同的步骤(因为客户端在未连接服务端时候,也相当于服务端,所以是等价的)

1. GameInstance的Init函数被调用

2. GameMode中的OnPostLogin被调用,相当于自身连接到自身,所以会触发一个OnPostLogin(注意OnPostLogin是早于任何Actor的BeginPlay的)

3. PlayerController的BeginPlay被调用(这里只测试了PlayerController的,PlayerState,GameMode,GameState等其他几个相关类的BeginPlay也应该是这个阶段,只是先后顺序我并没有测试)

4. 关卡被加载

之后服务端创建了Session,客户端查找并连接到Session,这个步骤是人为的,不是固定的

----------------------------------------------------------------------------------------------------------

在连接到Session的瞬间发生了如下事件:(这里是重点)

1. 客户端的PlayerController被重新生成了(老的被销毁,生成了一个新的),并传参给GameMode的OnPostLogin事件。此时根据逻辑来说,PlayerState应该也被重新生成了。服务端的PlayerController目测应该还是之前的那个,并没有重新生成

2. GameMode(只存在于服务端)的OnPostLogin被调用,记录在GameState中的PlayerArray中增加了元素

3. 客户端的地图又被加载,而此过程中服务端的地图并没有发生任何变化

(注意上面2和3的步骤顺序并不一定正确)

GameState和GameMode

这里需要知道,客户端的GameMode被无情抛弃,因为只存在于服务器上。实际上客户端"老的”GameState也被抛弃了,现在都从服务器上同步了一个新的GameState。

GameInstance

GameInstance仍存在与每个实例中,没有发生任何改变,没有被销毁或者重生,也不会被网络同步,自己的就是自己的,所以适合于记录一些每个客户端特定的信息。

但是从服务器端要想访问到某个客户端的GameInstance,需要费点周折,要使用从客户端运行的(Run on owning Client)函数,或者利用replicated的对象,在其蓝图中加一个Swith has authority,然后在其remote后面获取GameInstance。

总结一下:说简单点,客户端连接服务端以后,实际上只"带过来"了PlayerController(还是新生成的)和GameInstance(这个很专一,自始自终没有变,除非客户端程序被关闭),剩下的都要重新建立,比如地图要加载,Pawn要重新生成(在PostLogin过程中),PlayerState要重新生成,GameMode没了,GameState也要从服务器上同步一个过来。

----------------------------------------------------------------------------------------------------------

上一篇:UE4 内容示例网络同步Learn


下一篇:解读BOM与COM