6 - Remote Procedure Calls
概述
遠程過程呼叫,或稱RPC,是任何網路庫中最常見的功能之一,它與常規方法的直觀映射使得它在試圖將多個客戶端聚集在一個共享的世界中時很容易成為第一選擇,不幸的是它往往不是最好的選擇。
在像Fusion這樣的基於tick的狀態同步庫中,RPC可能會有問題,因為它們並不與特定的tick相聯繫,而且會在不同的客戶端上的不同時間執行。但也許更重要的是,它們不是網路狀態的一部分,所以任何在RPC發送後連接或重新連接的玩家,或者只是因為它被不可靠地發送而沒有收到它,都不會看到它的後果。
在大多數情況下,狀態同步本身就足以讓玩家保持一致,給聯網屬性添加一個OnChange監聽器可以處理大多數過渡情況,在這些情況下,應用程式關心的是狀態的變化,而不僅僅是實際狀態本身。
不過,在有些用例中,RPC是一個不錯的選擇,這裡有幾個例子:
- 發送嘲諷信息或其他不穩定的玩家之間的非遊戲互動。
- 從遊戲中的商店購買裝備,準確的時間並不重要,RPC呼叫的直接結果(扣除資金和添加到庫存)只對呼叫的玩家重要。(也就是說,不要用RPC來裝備上述購買的裝備)。
- 設置玩家的初始屬性,如姓名、顏色、皮膚。(即任何直接由玩家的”罕見”輸入造成的結果。基本上,任何您不希望在每回合輸入結構中出現的玩家輸入都是如此)。
- 啟動遊戲(對遊戲模式、地圖進行投票,或只是向主機表明玩家已準備好)。
Fusion RPCs
在少數情況下,RPCs是正確的選擇,Fusion確實讓它變得非常簡單。只需在任何SimulationBehaviour
上用RPC屬性標記一個常規方法,並說明誰可以呼叫該方法,以及誰應該接收該呼叫。確保該方法的前綴或後綴為RPC
(沒有特別的大寫),您就可以呼叫它了。
這個小例子的目標是在按下R
鍵時向所有其他玩家發送一條Hello Mate!
訊息。
呼叫RPC
在添加RPC本身之前,需要對輸入處理進行擴展。由於RPC呼叫是實際的網路化訊息,因此不需要擴展輸入結構。另外,由於RPC無論如何都不是tick對齊的,所以沒有必要使用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 Text _messages;
[Rpc(RpcSources.InputAuthority, RpcTargets.All)]
public void RPC_SendMessage(string message, RpcInfo info = default)
{
if (_messages == null)
_messages = FindObjectOfType<Text>();
if (info.Source == Runner.Simulation.LocalPlayer)
message = $"You said: {message}\n";
else
message = $"Some other player said: {message}\n";
_messages.text += message;
}
RPCSources.InputAuthority
和RPCTargets.All
參數告訴Fusion只讓對玩家有輸入權限的客戶端呼叫這個方法,但在所有客戶端上執行。
代碼本身只是簡單地搜索場景中的任何文本字段,並將消息附加到該字段中,所以為了測試這一點,請繼續添加一個文本組件。
GameObject > UI > Text
改變文本字段的大小以填滿整個螢幕介面,這樣會更容易閱讀文本。
Back to top