6 - Remote Procedure Calls
概述
遠端程序調用,或RPC,是任何網路程式庫的最常見的功能之一,其到常規方法的直觀映射,使其成為嘗試將多個客戶端聚集在一個共享世界中的方便首選。不幸的是,這往往不是最好的選擇。
RPC在Fusion這樣的基於刷新的狀態同步程式庫中可能會出現問題,因為它們不綁定到特定的刷新,並且將在不同的客戶端上的不同時間執行。但也許更重要的是,它們不是網路狀態的一部分,因此任何在RPC發送後連線或重新連線的玩家,或者只是因為發送不可靠而沒有收到它,就永遠不會看到它的結果。
在大多數情況下,狀態同步本身就足以保持玩家的一致性,向網路屬性新增OnChange接聽器可以處理大多數過渡情況,也就是應用程式在意狀態的更改,而不僅僅是實際狀態本身的情況。
儘管如此,在某些使用案例中RPC是一個不錯的選擇,以下是幾個示例:
- 在玩家之間發送嘲諷訊息或其他情緒性的非遊戲遊玩互動。
- 從遊戲內商店購買裝備,在那裡確切的時間並不重要,而RPC調用的直接結果(扣除資金和新增存貨)只對發出調用的玩家而言重要。(也就是,不要使用RPC來裝備該購買物)
- 設定初始玩家屬性,如名稱、顏色、皮膚。(也就是說,來自玩家的「稀有」輸入的直接結果。基本上是您不想在每個刷新輸入架構中有的任何玩家輸入)
- 啟動遊戲(在遊戲模式、地圖上投票,或者只是向主機端指出玩家已經準備好)。
Fusion RPC
在少數RPC是正確的選擇的情況下,Fusion又讓它變得非常簡單。只需在任何NetworkBehaviour
上用RPC屬性標記一個常規方法,並指示誰可以調用該方法以及誰將接收該調用。確保該方法的前綴或後綴有「RPC」(沒有特別要大寫字母),那麼您已經準備好調用它了。
這個小例子的目標是在按下R
鍵時向所有其他玩家發送「你好,夥伴!」的訊息。
調用RPC
首先將文字欄位新增到場景中:
GameObject > UI > Text - TextMeshPro
(如需要則匯入TextMeshPro基礎版)。更改文字欄位的大小以填充整個畫面,這樣可以更容易地閱讀文字。
在新增RPC本身之前,需要擴展輸入處理。由於RPC調用是實際的已連網訊息,因此不需要擴展輸入架構。此外,由於RPC無論如何都不是刷新對齊的,因此不需要使用Fusions輸入處理,所以開啟Player.cs
並新增:
C#
private void Update()
{
if (Object.HasInputAuthority && Input.GetKeyDown(KeyCode.R))
{
RPC_SendMessage("Hey Mate!");
}
}
請注意檢查Object.HasInputAuthority
-這是因為這個程式碼在所有客戶端上運行,但應該只有控制這個玩家的客戶端能調用RPC。
RPC實作
當仍在Player.cs
中時,也要新增RPC主體本身。它被標記為[Rpc]
屬性,方法名稱以「RPC」開頭。像這樣:
C#
private TMP_Text _messages;
[Rpc(RpcSources.InputAuthority, RpcTargets.StateAuthority, HostMode = RpcHostMode.SourceIsHostPlayer)]
public void RPC_SendMessage(string message, RpcInfo info = default)
{
RPC_RelayMessage(message, info.Source);
}
[Rpc(RpcSources.StateAuthority, RpcTargets.All, HostMode = RpcHostMode.SourceIsServer)]
public void RPC_RelayMessage(string message, PlayerRef messageSource)
{
if (_messages == null)
_messages = FindObjectOfType<TMP_Text>();
if (messageSource == Runner.LocalPlayer)
{
message = $"You said: {message}\n";
}
else
{
message = $"Some other player said: {message}\n";
}
_messages.text += message;
}
為什麼這裡有兩個RPC而不是一個?這是因為Fusion主機端模式是星形拓撲。客戶端無法直接使用RPC向其他客戶端發送資料。客戶端只能向主機端發送RPC,然後主機必須將訊息中繼到所有客戶端。
讓我們來看看SendMessage
RPC的屬性:
RpcSources.InputAuthority
=> 只有對物件具有輸入授權的客戶端才能觸發RPC來發送訊息。RpcTargets.StateAuthority
=> 發送訊息RPC被發送到主機端(狀態授權)。RpcHostMode.SourceIsHostPlayer
=> 由於主機端既是伺服器又是客戶端,因此需要指定調用RPC的主機端。
而對於RelayMessage
RPC:
RpcSources.StateAuthority
=> 伺服器/主機端正在發送此RPC。RpcTargets.All
=> 所有客戶端都應接收此RPC。HostMode = RpcHostMode.SourceIsServer
=> 主機應用程式的伺服器部分正在發送此RPC。
有了這個,只要玩家按下R
鍵,就會向每個客戶端傳輸一條訊息。
遊玩遊戲
至此,主機端模式基礎教學就完成了。建立一個組建並在兩個客戶端上進入遊玩模式。一個作為主機端,另一個作為客戶端。玩家可以四處移動,用滑鼠按鈕生成球體,並按下R
鍵發送RPC。
下一章是 主機端模式基礎7 - 下一步是什麼
Back to top