원격 프로시저 호출
소개
RPC(원격 프로시저 호출)는 특정 이벤트를 네트워크 클라이언트 간에 공유하기에 이상적입니다. 반면에, [Networked]
속성은 지속적으로 변하는 상태를 공유하는 데 적합한 기본 솔루션입니다.
예를 들어, 플레이어가 자신에게 입력 권한이 없는 객체(예: 인벤토리의 특정 키를 사용하여 잠긴 문을 여는 것)와 드문 복잡한 상호작용을 수행하려고 할 때 RPC를 사용할 수 있습니다. 기술적으로 입력 구조체에 추가 필드를 포함하여 이를 수행할 수 있지만, 이는 입력 구조체를 복잡하게 만들고 다루기 어렵게 만듭니다.
게다가 입력 구조체는 신뢰할 수 없는 메시지로 전송됩니다(즉, 패킷이 손실될 수 있음). 이는 지속적인 입력(예: 캐릭터 이동)에는 거의 영향을 미치지 않지만, 플레이어가 보장되기를 기대하는 단일 일회성 동작에는 치명적일 수 있습니다. 이 상황에서는 원격 프로시저 호출이 최선의 방법입니다.
RPC 생성
NetworkObject
의 NetworkBehaviour
에서 RPC를 정의하려면 다음 단계를 따르세요:
- 반환 타입이
void
또는RpcInvokeInfo
인 일반 C# 메서드를 선언합니다(아래 문서화됨). - 메서드 이름 앞뒤에 "RPC"를 추가합니다(대소문자 구분 없음).
- 메서드 선언 앞에
[Rpc]
속성을 추가합니다. RpcSources
및RpcTargets
매개변수를 설정하여 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는 약간의 다른 규칙을 따릅니다:
RpcSources
및RpcTargets
매개변수를 무시합니다.메서드의 첫 번째 매개변수는
NetworkRunner
여야 합니다.특정
NetworkObject
에 묶이지 않고, 모든SimulationBehaviour
에서 구현할 수 있습니다.
정적 RPC는 소스와 대상 필터가 없기 때문에 모든 클라이언트에서 호출될 수 있으며 모든 클라이언트로 전송됩니다. 그러나 특정 PlayerRef
를 대상으로 지정하여 호출 대상을 제어할 수 있습니다(Targeted RPC 참조).
C#
[Rpc]
public static void Rpc_MyStaticRpc(NetworkRunner runner, int a) { }
RPC 속성 매개변수
Sources와 Targets
RpcSources
와 RpcTargets
는 필터 역할을 합니다. 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 속성 매개변수
RpcSources
와 RpcTargets
외에도 [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 (직렬화 시
NetworkId
와NetworkBehaviour
인덱스로 변환) - PlayerRef (직렬화 시
PlayerRef.PlayerId
로 변환)
- NetworkObject (직렬화 시
- 문자열 (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.Source
는 PlayerRef.None
으로 설정됩니다. 이는 서버가 플레이어로 간주되지 않기 때문입니다.
Fusion이 HostMode
로 실행 중인 경우, 호스트-클라이언트는 서버와 플레이어 역할을 모두 수행합니다. 기본적으로, 호스트가 보낸 RPC는 서버와 동일하게 작동하며 RpcInfo.Source
는 PlayerRef.None
으로 설정됩니다. 호스트의 로컬 PlayerRef
를 포함하려면 HostMode
속성을 RpcHostMode.SourceIsHostPlayer
로 설정해야 합니다.
HostMode
는 두 가지 모드로 설정할 수 있습니다:
RpcHostMode.SourceIsServer
(기본값):RpcInfo.Source
는PlayerRef.None
으로 설정됩니다.RpcHostMode.SourceIsHostPlayer
: Fusion이HostMode
로 실행 중일 때RpcInfo.Source
는 로컬PlayerRef
로 설정됩니다.
호스트의 PlayerRef
를 RpcSource.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
매개변수와는 다릅니다.