This page is a work in progress and could be pending updates.

Remote Procedure Calls

簡介

遠程過程呼叫,簡稱RPC,是分享準時遊戲事件的理想選擇;相比之下,輸入結構和[Networked]屬性是在不斷變化的網路客戶端之間分享狀態的首選解決方案。

例如,當玩家想與一個它沒有輸入權限的對象進行罕見的複雜交互時,例如使用他們庫存清單中的特定鑰匙來打開一扇鎖著的門。雖然從技術上講,這些動作可以通過包括額外的字段作為輸入的一部分來執行,但這將使輸入結構變得雜亂無章,並使其變得不容易操作。此外,Input Struct是作為不可靠的訊息發送的,也就是說,數據包可能會丟失。這對於需要連續輸入的東西(例如角色的移動)來說很少注意到,但是當這影響到玩家期望得到保証的單一的一次性動作時,就會對玩家的體驗造成傷害。在這種情況下,遠程程序呼叫是最好的做法。

Back To Top

設置

Fusion有一個簡單而強大的RPCs語法。總的來說,有3種類型的RPCs:

  1. 事件RPCs。
  2. 靜態RPC;以及,
  3. 有針對性的RPCs。

這些類型中的每一種都將在下面的章節中介紹。

Back To Top

事件RPC

要在NetworkObject上的任何NetworkBehaviour上定義一個RPC,只需遵循以下步驟:

  1. 宣告一個常規的CSharp方法,返回類型為void
  2. 在方法宣告的前面添加[Rpc]屬性;以及,
  3. 配置RpcSourcesRpcTargets參數,以控制RPC的呼叫地點和執行地點。
[Rpc(source: RpcSources.InputAuthority, target: RpcTargets.StateAuthority)]
public void RPC_Configure(string name, Color color){
    playerName = name;
    playerColor = color;
}

一個RPC可以接受任何參數,並尊重Network Object > NetworkBehaviour > Networked State > Constraints條目中概述的類型約束。

Note: 在方法上使用RPC_前綴是一種慣例,以方便在代碼庫中搜索和識別RPC。

Back To Top

靜態RPC

靜態RPC遵循稍微不同的規則,它們:

  • 忽略RpcSourcesRpcTargets參數;以及
  • 要求方法的第一個參數是NetworkRunner
public static void Rpc_MyStaticRpc(NetworkRunner runner, int a) { }

Back To Top

RPC屬性參數

源頭和目標

RpcSourcesRpcTargets是過濾器。RpcSources定義了哪個對象可以發送RPC,而RpcTargets定義了它的執行對象。

  • All:可以被發送/被會話中的所有對象執行(包括伺服器)。
  • Proxies:可以被發送/由對該對象沒有輸入權限或狀態權限的對象執行。
  • InputAuthority:可以發送/由對該對象有輸入權限的對象執行。
  • StateAuthority:可以發送/由對該對象有狀態權限的對象執行。

IMPORTANT: RPCs沒有明確的狀態。設置RpcTargets.AllNOT向晚加入的客戶傳送訊息,而斷開連接和重新連接的客戶將忘記它曾經發生過。因此,關鍵是要確保RPC是以下兩種情況之一:

  • 真正瞬時的,沒有任何狀態的(例如聊天訊息);或者,
  • 它的效果間接地記錄在[Networked]屬性中。
public class Player : NetworkBehaviour {
    [Networked] public string playerName { get; set; }
    [Networked] public Color playerColor { get; set; }

    [Rpc(RpcSources.InputAuthority, RpcTargets.StateAuthority)]
    public void RPC_Configure(string name, Color color)    {
        playerName = name;
        playerColor = color;
    }
}

Back To Top

可選的RPC屬性參數

除了強制性的RpcSourcesRpcTargets屬性外,[Rpc]屬性還提供了幾個可選參數。

  • Channel(默認為Reliable):如果RPC在傳輸中可能丟失,則設置為Unreliable
  • InvokeLocal(默認為true):如果RPC不在本地客戶端上呼叫,則設置為false。
  • InvokeResim (默認為false):如果RPC在重新模擬時不被呼叫,則設置為true。
[Rpc (RpcSources.All, RpcTargets.All, InvokeLocal = true, InvokeResim = true )]
void RpcStartBoost(){
    m_BoostAnim.StartBoostAnimation();
}

Back To Top

RPC方法參數

RpcInfo

RPC方法declarations可以接受一個RpcInfo類型的可選參數。這允許讀出關於RPC的額外訊息。

  • Tick:在哪個時間點發送的。
  • Source:哪個玩家(PlayerRef)發送的。
  • Channel:它是作為Unreliable還是可靠的RPC發送的。
  • IsInvokeLocal:最初呼叫這個RPC的是本地玩家。
[Rpc(source: RpcSources.InputAuthority, target: RpcTargets.StateAuthority)]
public void RPC_Configure(string name, Color color, RpcInfo info = default){
    playerName = name;
    playerColor = color;
}

該參數always被宣告為RpcInfo info = default

Back To Top

有針對性的Rpc

當一個RPC要在特定玩家的機器上專門執行時,就會使用所謂的目標RPC。事件RPC和靜態RPC都可以變成目標RPC,方法是在[RpcTarget]屬性前添加一個PlayerRef參數。一個典型的用例是團隊聊天,一個消息只針對自己團隊中的特定玩家。

[Rpc(source: RpcSources.InputAuthority, target: RpcTargets.StateAuthority)]
public void Rpc_TargetedInstanceMessage([RpcTarget] PlayerRef player, string message){}

public static void Rpc_MyTargetedStaticMessage(NetworkRunner runner, [RpcTarget] PlayerRef player, string message) { };

IMPORTANT: 在方法宣告中使用的[RpcTarget]屬性與方法宣告前的[Rpc]屬性中的RpcTargets參數是不同的。

To Document Top