This document is about: FUSION 2
SWITCH TO

6 - Remote Procedure Calls

概述

遠端程序調用,或RPC,是任何網路程式庫的最常見的功能之一,其到常規方法的直觀映射,使其成為嘗試將多個客戶端聚集在一個共享世界中的方便首選。不幸的是,這往往不是最好的選擇。

RPC在Fusion這樣的基於刷新的狀態同步程式庫中可能會出現問題,因為它們不綁定到特定的刷新,並且將在不同的客戶端上的不同時間執行。但也許更重要的是,它們不是網路狀態的一部分,因此任何在RPC發送後連線或重新連線的玩家,或者只是因為發送不可靠而沒有收到它,就永遠不會看到它的結果。

在大多數情況下,狀態同步本身就足以保持玩家的一致性,向網路屬性新增OnChange接聽器可以處理大多數過渡情況,也就是應用程式在意狀態的更改,而不僅僅是實際狀態本身的情況。

儘管如此,在某些使用案例中RPC是一個不錯的選擇,以下是幾個示例:

  1. 在玩家之間發送嘲諷訊息或其他情緒性的非遊戲遊玩互動。
  2. 從遊戲內商店購買裝備,在那裡確切的時間並不重要,而RPC調用的直接結果(扣除資金和新增存貨)只對發出調用的玩家而言重要。(也就是,不要使用RPC來裝備該購買物)
  3. 設定初始玩家屬性,如名稱、顏色、皮膚。(也就是說,來自玩家的「稀有」輸入的直接結果。基本上是您不想在每個刷新輸入架構中有的任何玩家輸入)
  4. 啟動遊戲(在遊戲模式、地圖上投票,或者只是向主機端指出玩家已經準備好)。

有關此主題的詳細描述,請參閱操作手冊

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