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