This document is about: FUSION 2
SWITCH TO

원격 프로시저 호출

소개

RPC(원격 프로시저 호출)는 특정 이벤트를 네트워크 클라이언트 간에 공유하기에 이상적입니다. 반면에, [Networked] 속성은 지속적으로 변하는 상태를 공유하는 데 적합한 기본 솔루션입니다.

예를 들어, 플레이어가 자신에게 입력 권한이 없는 객체(예: 인벤토리의 특정 키를 사용하여 잠긴 문을 여는 것)와 드문 복잡한 상호작용을 수행하려고 할 때 RPC를 사용할 수 있습니다. 기술적으로 입력 구조체에 추가 필드를 포함하여 이를 수행할 수 있지만, 이는 입력 구조체를 복잡하게 만들고 다루기 어렵게 만듭니다.

게다가 입력 구조체는 신뢰할 수 없는 메시지로 전송됩니다(즉, 패킷이 손실될 수 있음). 이는 지속적인 입력(예: 캐릭터 이동)에는 거의 영향을 미치지 않지만, 플레이어가 보장되기를 기대하는 단일 일회성 동작에는 치명적일 수 있습니다. 이 상황에서는 원격 프로시저 호출이 최선의 방법입니다.

RPC 생성

NetworkObjectNetworkBehaviour에서 RPC를 정의하려면 다음 단계를 따르세요:

  1. 반환 타입이 void 또는 RpcInvokeInfo인 일반 C# 메서드를 선언합니다(아래 문서화됨).
  2. 메서드 이름 앞뒤에 "RPC"를 추가합니다(대소문자 구분 없음).
  3. 메서드 선언 앞에 [Rpc] 속성을 추가합니다.
  4. RpcSourcesRpcTargets 매개변수를 설정하여 RPC 호출 위치와 실행 위치를 제어합니다.

C#

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

RPC는 작동하려면 메서드 이름에 "RPC" 접두사 또는 접미사가 필요합니다.

정적 RPC

정적 RPC는 약간의 다른 규칙을 따릅니다:

  • RpcSourcesRpcTargets 매개변수를 무시합니다.

  • 메서드의 첫 번째 매개변수는 NetworkRunner여야 합니다.

  • 특정 NetworkObject에 묶이지 않고, 모든 SimulationBehaviour에서 구현할 수 있습니다.

정적 RPC는 소스와 대상 필터가 없기 때문에 모든 클라이언트에서 호출될 수 있으며 모든 클라이언트로 전송됩니다. 그러나 특정 PlayerRef를 대상으로 지정하여 호출 대상을 제어할 수 있습니다(Targeted RPC 참조).

C#

[Rpc]
public static void Rpc_MyStaticRpc(NetworkRunner runner, int a) { }

RPC 속성 매개변수

Sources와 Targets

RpcSourcesRpcTargets는 필터 역할을 합니다. RpcSources는 RPC를 보낼 수 있는 피어를 정의하고, RpcTargets는 실행될 피어를 정의합니다.

  • All: 세션 내 모든 피어(서버 포함)에서 보낼 수 있으며, 실행됩니다.
  • Proxies: 입력 권한(Input Authority)이나 상태 권한(State Authority)이 없는 피어에서 보낼 수 있으며, 실행됩니다.
  • InputAuthority: 해당 객체에 입력 권한을 가진 피어에서 보낼 수 있으며, 실행됩니다.
  • StateAuthority: 해당 객체에 상태 권한을 가진 피어에서 보낼 수 있으며, 실행됩니다.

중요: RPC는 명시적 상태를 가지지 않습니다. 늦게 접속한 클라이언트와 연결이 끊긴 후 다시 연결된 클라이언트는 RPC가 발생한 사실을 잊게 됩니다. 따라서 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 속성 매개변수

RpcSourcesRpcTargets 외에도 [Rpc] 속성은 몇 가지 선택적 매개변수를 제공합니다:

  • Channel (기본값 Reliable): RPC가 전송 중 손실되어도 되는 경우 Unreliable로 설정합니다.
  • InvokeLocal (기본값 true): RPC가 로컬 클라이언트에서 호출되는지 여부를 나타냅니다.
  • TickAligned (기본값 true): RPC가 전송된 틱 이후에 실행을 지연하지 않으려면 false로 설정합니다.

C#

[Rpc (RpcSources.All, RpcTargets.All, InvokeLocal = true, TickAligned = false )]
void RpcStartBoost(){
    m_BoostAnim.StartBoostAnimation();
}

RPC 메소드 매개변수

RPC는 런타임에 직렬화됩니다. 따라서 Fusion 전용 타입(e.g., NetworkBool)보다는 일반 CLR 타입(e.g., bool)을 사용하는 것이 권장됩니다.

지원되는 타입

RPC에서 지원되는 타입은 다음과 같습니다:

  • 기본 타입(Primitives)
    • byte, sbyte
    • Int16, Int32, Int64
    • UInt16, UInt32, UInt64
    • float
    • double
    • float
    • double
  • Unity 구조체 타입 (ILWeaver.cs에 정의됨)
    • Vector2, Vector3, Vector4
    • Quaternion
    • Matrix4x4
    • Vector2Int, Vector3Int
    • BoundingSphere
    • Bounds
    • Rect
    • BoundsInt
    • RectInt
    • Color, Color32
  • System.Guid
  • 사용자 정의 INetworkStructs
  • Fusion 정의 INetworkStructs
    • NetworkString<IFixedStorage>
    • NetworkBool
    • Ptr
    • Angle
    • BitSet64, BitSet128, BitSet192, BitSet256
    • PlayerRefSet
    • NetworkId
    • NetworkButtons
    • NetworkRNG
    • NetworkObjectGuid
    • NetworkPrefabRef
    • NetworkObjectHeader
    • NetworkPrefabId
    • SceneRef
    • TickTimer
    • IFixedStorage (_2, _4, _8, _16, _32, _64, _128, _256, _512)
  • Fusion 타입
    • NetworkObject (직렬화 시 NetworkId로 변환)
    • NetworkBehaviour (직렬화 시 NetworkIdNetworkBehaviour 인덱스로 변환)
    • PlayerRef (직렬화 시 PlayerRef.PlayerId로 변환)
  • 문자열 (Strings)
  • 위에 나열된 타입의 배열

RpcInfo

RPC 메서드 선언에는 선택적으로 RpcInfo 타입의 매개변수를 추가할 수 있으며, 이를 통해 RPC에 대한 다음과 같은 메타 정보를 제공합니다:

  • Tick: RPC가 전송된 틱.
  • Source: RPC를 보낸 플레이어(PlayerRef).
  • Channel: RPC가 Unreliable로 전송되었는지 Reliable로 전송되었는지 여부.
  • IsInvokeLocal: RPC가 로컬 플레이어에 의해 호출되었는지 여부.

C#

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

매개변수는 항상 RpcInfo info = default로 선언됩니다.

{% if Fusion_v2 %}

서버와 호스트 소스

Fusion이 ServerMode로 실행 중인 경우, 서버에서 보낸 RPC의 RpcInfo.SourcePlayerRef.None으로 설정됩니다. 이는 서버가 플레이어로 간주되지 않기 때문입니다.

Fusion이 HostMode로 실행 중인 경우, 호스트-클라이언트는 서버와 플레이어 역할을 모두 수행합니다. 기본적으로, 호스트가 보낸 RPC는 서버와 동일하게 작동하며 RpcInfo.SourcePlayerRef.None으로 설정됩니다. 호스트의 로컬 PlayerRef를 포함하려면 HostMode 속성을 RpcHostMode.SourceIsHostPlayer로 설정해야 합니다.

HostMode는 두 가지 모드로 설정할 수 있습니다:

  • RpcHostMode.SourceIsServer (기본값): RpcInfo.SourcePlayerRef.None으로 설정됩니다.
  • RpcHostMode.SourceIsHostPlayer: Fusion이 HostMode로 실행 중일 때 RpcInfo.Source는 로컬 PlayerRef로 설정됩니다.

호스트의 PlayerRefRpcSource.Info에 포함하려면 아래와 같이 코드를 조정할 수 있습니다:

C#

[Rpc(sources: RpcSources.InputAuthority, targets: RpcTargets.StateAuthority, HostMode = RpcHostMode.SourceIsHostPlayer)]
public void RPC_Configure(string name, Color color, RpcInfo info = default){
    playerName = name;
    playerColor = color;
}

RpcInvokeInfo

RPC 메서드는 선택적으로 반환값으로 RpcInvokeInfo를 정의할 수 있습니다. RPC 메서드가 호출될 때, RpcInvokeInfo 반환값은 RPC 호출 및 전송 작업에 대한 정보를 제공합니다.

  • LocalInvokeResult: 로컬 호출 동작의 성공 또는 실패 원인을 나타내는 RpcLocalInvokeResult 열거형 값.
  • SendCullResult: 원격 피어에 대한 RPC 호출 성공 또는 실패 원인을 나타내는 RpcSendCullResult 열거형 값.
  • SendResult: RPC 전송 작업에 대한 메타 정보를 포함하는 RpcSendResult 구조체.
    • Result: 이 RPC 메시지 전송 작업의 결과 플래그(RpcSendMessageResult).
    • MessageSize: RPC 패키지 크기.
    • Receivers: 이 RPC 작업의 수신자로 포함된 PlayerRef의 컬렉션.
    • CulledReceivers: 이 RPC 전송 작업에서 제외된 PlayerRef의 컬렉션.

참고: 이는 전송 성공 여부에 대한 정보가 아니라, 호출전송 작업의 결과만 제공합니다.

C#

[Rpc]
public RpcInvokeInfo RpcFoo() {
  // RPC 작업
  return default;
}
 
public override void FixedUpdateNetwork() {
  var info = RpcFoo();
  Debug.Log(info);
}

타겟팅 된 RPC

특정 플레이어의 기계에서만 실행되도록 RPC를 설정하려면 타겟팅 된 RPC를 사용합니다. 인스턴스 RPC와 정적 RPC 모두 PlayerRef 매개변수를 추가하고 [RpcTarget] 속성을 사용하여 타겟팅 된 RPC로 전환할 수 있습니다. 일반적인 사용 사례는 팀 채팅으로, 메시지가 자신의 팀원에게만 전달되는 경우입니다.

주의

[RpcTarget] 매개변수에 PlayerRef.None을 전달하면 서버를 대상으로 지정합니다!

C#

[Rpc(sources: RpcSources.InputAuthority, targets: RpcTargets.All)]
public void Rpc_TargetedInstanceMessage([RpcTarget] PlayerRef player, string message){}

또는

C#

[Rpc(sources: RpcSources.InputAuthority, targets: RpcTargets.All)]
public static void Rpc_MyTargetedStaticMessage(NetworkRunner runner, [RpcTarget] PlayerRef player, string message) { };
중요

메서드 내에서 사용하는 [RpcTarget] 속성은 메서드 선언 앞에 있는 [Rpc] 속성의 RpcTargets 매개변수와는 다릅니다.

Back to top