Remote Procedure Calls
簡介
遠程過程呼叫,簡稱RPC,是分享準時遊戲事件的理想選擇;相比之下,輸入結構和[Networked]屬性是在不斷變化的網路客戶端之間分享狀態的首選解決方案。
例如,當玩家想與一個它沒有輸入權限的對象進行罕見的複雜交互時,例如使用他們庫存清單中的特定鑰匙來打開一扇鎖著的門。雖然從技術上講,這些動作可以通過包括額外的字段作為輸入的一部分來執行,但這將使輸入結構變得雜亂無章,並使其變得不容易操作。此外,Input Struct是作為不可靠的訊息發送的,也就是說,數據包可能會丟失。這對於需要連續輸入的東西(例如角色的移動)來說很少注意到,但是當這影響到玩家期望得到保証的單一的一次性動作時,就會對玩家的體驗造成傷害。在這種情況下,遠程程序呼叫是最好的做法。
設置
Fusion有一個簡單而強大的RPCs語法。總的來說,有3種類型的RPCs:
- 事件RPCs。
- 靜態RPC;以及,
- 有針對性的RPCs。
這些類型中的每一種都將在下面的章節中介紹。
事件RPC
要在NetworkObject上的任何NetworkBehaviour上定義一個RPC,只需遵循以下步驟:
- 宣告一個常規的CSharp方法,返回類型為void。
- 在方法宣告的前面添加[Rpc]屬性;以及,
- 配置RpcSources和RpcTargets參數,以控制RPC的呼叫地點和執行地點。
C#
[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。
靜態RPC
靜態RPC遵循稍微不同的規則,它們:
- 忽略RpcSources和RpcTargets參數;以及
- 要求方法的第一個參數是NetworkRunner。
C#
public static void Rpc_MyStaticRpc(NetworkRunner runner, int a) { }
RPC屬性參數
源頭和目標
RpcSources和RpcTargets是過濾器。RpcSources定義了哪個對象可以發送RPC,而RpcTargets定義了它的執行對象。
- All:可以被發送/被會話中的所有對象執行(包括伺服器)。
- Proxies:可以被發送/由對該對象沒有輸入權限或狀態權限的對象執行。
- InputAuthority:可以發送/由對該對象有輸入權限的對象執行。
- StateAuthority:可以發送/由對該對象有狀態權限的對象執行。
IMPORTANT: RPCs沒有明確的狀態。設置RpcTargets.All將__NOT__向晚加入的客戶傳送訊息,而斷開連接和重新連接的客戶將忘記它曾經發生過。因此,關鍵是要確保RPC是以下兩種情況之一:
- 真正瞬時的,沒有任何狀態的(例如聊天訊息);或者,
- 它的效果間接地記錄在[Networked]屬性中。
C#
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;
    }
}
可選的RPC屬性參數
除了強制性的RpcSources和RpcTargets屬性外,[Rpc]屬性還提供了幾個可選參數。
- Channel(默認為- Reliable):如果RPC在傳輸中可能丟失,則設置為- Unreliable。
- InvokeLocal(默認為true):如果RPC不在本地客戶端上呼叫,則設置為false。
- InvokeResim(默認為false):如果RPC在重新模擬時不被呼叫,則設置為true。
C#
[Rpc (RpcSources.All, RpcTargets.All, InvokeLocal = true, InvokeResim = true )]
void RpcStartBoost(){
    m_BoostAnim.StartBoostAnimation();
}
RPC方法參數
RpcInfo
RPC方法_declarations_可以接受一個RpcInfo類型的可選參數。這允許讀出關於RPC的額外訊息。
- Tick:在哪個時間點發送的。
- Source:哪個玩家(- PlayerRef)發送的。
- Channel:它是作為- Unreliable還是- 可靠的RPC發送的。
- IsInvokeLocal:最初呼叫這個RPC的是本地玩家。
C#
[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。
有針對性的Rpc
當一個RPC要在特定玩家的機器上專門執行時,就會使用所謂的目標RPC。事件RPC和靜態RPC都可以變成目標RPC,方法是在[RpcTarget]屬性前添加一個PlayerRef參數。一個典型的用例是團隊聊天,一個消息只針對自己團隊中的特定玩家。
C#
[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參數是不同的。