Replicate(网络复制),ActorRole(角色),Ownership(所有权)以及RPC(远程调用)等等...
I. Replication
Replication指的是 從服務端向客戶端 傳遞數據和信息的行為。注意是單向的,不會從客戶端傳遞信息和數據到服務端。
假設一個Actor被設置為Replicates, 當且僅當它被服務端生成 ,那么它會被所有客戶端生成,并被Replicated。言外之意,即使是Replicates的Actor,如果在某個客戶端生成,它也只會在本客戶端生成,是 不會在其他客戶端或者服務端生成 的,自然也談不上Replication。
還有一種情況容易讓人糊涂:假設在Pawn類中的Authority端生成一個Actor,并且把它存為變量,那么這個變量的Replicates屬性和這個Actor本身的Replicates屬性是什么關系?實際上,這里變量只是指向這個Actor的一個引用/指針,掌握住這點就好理解了。如果這個Actor沒有Replicates,而讓這個指針Replicates,那么它在客戶端上就會指向一個NULL,這個并不會讓引擎崩潰,但是沒有任何意義。如果Actor Replicates,但是指針不是Replicated,那么在客戶端這個Actor是存在的,但是指針沒辦法指向正確的對象。所以這種情況下需要Actor和變量都是Replicates(ed)才能達到正確的效果
另外,GameMode是不會Replicates的,它只存在于服務端,所以對它存儲的變量設置Replicated沒有任何意義。
?
那么再考慮一下,如果這個Actor在編輯階段就被置于場景中呢,它在多人聯網的情形下是什么狀況?
我做了以下幾個實驗來逐步分析:
(以下實驗如無特殊說明,均采用默認的第三人稱場景,Play選項Number of Players選擇2,New Editor Window(PIE))
實驗1:Actor不勾選Replicates,直接放置于場景中,初始一個隨機速度運動
結果:客戶端和服務端都各自以各自的速度運動,證明這兩個物體在不同的instance上是獨立的,互無關聯的。
?
實驗2:Actor勾選Replicates,但不勾選Replicate Movement,直接放置于場景中,初始一個隨機速度運動
結果:和實驗1一樣。那么大家可能就會懷疑,這種情況下是不是和實驗1是完全一樣的?實際上和實驗1有很大的區別,這個Actor有了Replication,也就可以進行屬性的Replicates和RPC調用,而實驗1里的Actor就不可能進行這些操作。
?
實驗3:Actor勾選Replicates,勾選Replicate Movement,直接放置于場景中,初始一個隨機速度運動
結果:雖然初始化了不同的速度(print出來了),但是服務端和客戶端運動基本上是同步的,只是客戶端的運動會有些許“抖動”。出現這種情況的原因是客戶端“想”以自己的速度去運動,但是由于更新了Replicate Movement,服務端會以固定的頻率去把自身的位置同步給客戶端,因此客戶端會在更新的瞬間跳躍到服務器指定的位置,從而產生了抖動。
?
放置于場景中的Actor的情況我們搞清楚了,再來考慮一下更麻煩的——動態生成:
實驗4:我們先在LevelBlueprint的BeginPlay中直接生成Actor,這個Actor是實驗2的,也就是Actor勾選了Replicate,但并不同步移動。
結果:服務端有一個Actor,客戶端有2個Actor,并且3個Actor均以不同的速度在運動。不難理解,因為在LevelBP中生成,所以服務端生成了一個,但是這個Actor是Replicates的,所以被復制到客戶端,同時客戶端本身的LevelBP中也生成了一個,所以客戶端有兩個。
所以如果要在LevelBlueprint中生成Replicates的Actor,一定要在前面加上Switch has authority,并在Authority后面生成。
?上述幾個實驗的工程源碼存放在這里
?
II. Ownership
所謂“Own”(擁有)的主語其實是一個“連接”的實例或者PlayerController。
每個“連接”的實例肯定會Own(擁有)一個PlayerController
那么決定一個Actor是否被擁有,就是向上查找他的Ownership結構樹,找到最上層的擁有者,如果是個PlayerController,它就被這個PlayerController以及它的“連接”所擁有。
最典型的的例子,一個Pawn被PlayerController Possess的時候它就被Owned。如果它被Unposses了,Ownership也就丟失了。
那么一個普通的Actor能不能被“擁有”呢?答案是可以的,使用Set Owner方法就可以讓他被某個PlayerController擁有。
為什么要強調Ownership呢?
- 后面我們將描述這個問題:RPC需要決定在哪個客戶端執行 Run on Client的 RPC
- Actor網絡復制和連接的Rlevancy(相關性)
- 牽扯到Owner時候的property Replication條件
?
III. Actor Role 和 Remote Role
Actor Role在我的 這篇文章里已經很詳細的描述過了,這里做一下補充:
Actor Role 和 Remote Role是一組相對的概念,Actor Role指的是在本地的角色,Remote Role指的是遠程端的角色。這里的“遠程端”有點tricky,容易誤解,我也是糊涂了很久才明白。
設想有一個服務端加兩個或兩個以上的客戶端,那么所謂的“遠程端”到底指的是在哪個“端”?實際上我們只需要分兩個“端”,一個服務端,一個客戶端,把所有的客戶端都看成一端,這個問題的答案就很顯而易見了。
另外 官方文檔專門說明了, “目前,僅服務端可以負責同步信息到客戶端,因此僅服務端可以看到Role=Authority,并且RemoteRole=Simulated_Proxy或者Autonomous_Proxy”,這個“目前”說的是目前的網絡構架。
總之,只有服務端才可能有Authority,所有Replicates的Actor在服務端的Role都是Authority,要牢記這點。(非Replciates的有沒有Authority?有待驗證)
實際上,Simulated_Proxy和Autonomous_Proxy講的是兩種同步模式(Mode of Replication),因為服務器不可能每一幀都去把信息同步給所有客戶端,而是以一定的頻率去下發信息,那么兩次下發之間的空白怎么填補呢?虛幻設計了兩種同步的模式:
Simulated_Proxy是標準模式,用最后的速度和位置去移動物體.(使用最后的速度只是一種算法,你也可以實施自己的算法)
Autonomous_Proxy基本上只會用于被PlayerController 所Possess的對象(那就是被Possess的Pawn啦),那么在空白期間就直接用用戶的操作來填補。
看到這里,我們需要明確兩點:
- Autonomous_Proxy就是Pawn(當然說的是被Possess的)在本客戶端的Role——目前我能想到僅有這一種情況。它的RemoteRole——也就是在服務端的Role是Authority,它在其他客戶端的Role是Simulated_Proxy。
- 而任何非Pawn的Actor,在服務端的Role都是Authority,他們的RemoteRole都是SimulatedProxy。
在C++中可以使用Role==XXX來判斷一個Pawn的Role,但是在藍圖中我們可能需要分兩步來進行:首先判斷是否has authority,如果是,則是服務端,如果否,還要繼續判斷pawn是否isLocallyControlled,如果是,則是Autonomous_Proxy,如果否則是Simulated_Proxy。
IV. Actor Role和Ownership的關系
很重要的一點, Actor Role 和 Ownership沒有任何關系 ,是不同的概念。
只是很巧合,Autonomous_Proxy肯定會被Own,但不能說被Own了就一定是Autonomous_Proxy,例如我們可以對一個非Pawn的Actor 設置所有者(Set Owner),但是它的Actor Role沒有改變。
V. RPC
- RPC本質是用來調用在 另外一個游戲實例上的函數的 。
- RPC無法獲取返回值 ,這就是為為什么沒辦法把藍圖中的Function設置為RPC的原因,因為Function是可以帶返回值的。而CustomEvent是沒法設置返回值的,所以RPC只能標記在CustomEvent上。
- RPC分三種,Run on Server,Run on owning Client,NetMulticast
- RPC必須在Actor或者其子類上調用
- Actor必須是Replicated的(否則不存在RPC一說)
1. Run on Server
表示在Actor的服務端實例上執行。
如果RPC是從客戶端調用,讓其在服務端執行,客戶端必須 Own(擁有) 這個Actor。
2. Run on owning Client
表示在Actor的Owner上執行。
如果RPC是從服務端調用,讓其在客戶端執行,只有 Own(擁有) 這個Actor的客戶端才會執行。
注意Run on Server和 Run on owning Client的條件:客戶端必須Own這個Actor,也就是 這個Actor必須有Ownership 。
3. NetMulticast
表示在Actor的所有實例上執行。
如前所述,前兩種RPC模式都要求Actor必須有Ownership。 Multicast是個例外,它不需要OwnerShip 。
如果從服務端調用,服務端會本地執行,所有目前連接的客戶端也都會執行。
如果從客戶端端執行,則只會本地執行,服務端不會執行,其他客戶端也不會執行。
?
轉載于:https://www.cnblogs.com/AnKen/p/8602233.html
總結
以上是生活随笔為你收集整理的Replicate(网络复制),ActorRole(角色),Ownership(所有权)以及RPC(远程调用)等等...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CSS3如何实现0.5边框
- 下一篇: Python基础综合练习