Remote Procedure Calls
소개
간단히 RPC라고 하는 원격 프로시저 호출은 정확한 게임 이벤트를 공유하는 데 이상적입니다. 이와 대조적으로 입력 구조체 및 [Networked]
속성은 지속적으로 변경되는 네트워크 클라이언트 간에 상태를 공유하는 데 필요한 솔루션입니다.
예를 들어 플레이어가 인벤토리의 특정 키를 사용하여 잠긴 문을 여는 등 입력 권한이 없는 개체와 드물지만 복잡한 상호 작용을 수행하려고 할 때입니다. 추가 필드를 입력의 일부로 포함하면 기술적으로 작업을 수행할 수 있지만, 입력 구조체가 혼란스럽고 다루기 어렵게 됩니다. 또한, 입력 구조체는 신뢰할 수 없는 메시지로 전송됩니다. 즉, 패킷이 손실될 수 있습니다. 이는 지속적인 입력(예: 캐릭터 이동)이 필요한 경우 거의 눈에 띄지 않지만 플레이어가 보장받을 것으로 예상되는 일회성 동작에 영향을 미칠 경우 플레이어 경험에 해로울 수 있습니다. 이러한 상황에서는 원격 프로시저 호출이 가장 좋습니다.
또한 입력 구조체는 신뢰할 수 없는 메시지로 전송됩니다. 즉, 패킷이 손실될 수 있습니다. 이것은 연속적인 입력(예: 캐릭터 이동)이 필요한 경우에는 거의 눈에 띄지 않지만, 이것이 플레이어가 보장받을 것으로 예상되는 단일 일회성 액션에 영향을 미칠 때 플레이어 경험에 해로울 수 있습니다. 이 경우 원격 프로시저 호출이 가장 좋은 방법입니다.
설정
Fusion은 간단하지만 강력한 RPC 용 구문을 가지고 있습니다. 실제로 말하는 RPC에는 세 가지 유형이 있습니다.
- 인스턴스 RPC
- 정적 RPC 및
- 대상 RPC.
이러한 유형 각각은 다음 섹션에서 설명됩니다.
인스턴스 RPC
NetworkBehaviour
의 NetworkBehaviour
에 RPC를 정의하려면 다음 단계를 수행하세요.
- 리턴 타입이
void
또는RpcInvokeInfo
인 일반적인 CSharp 메소드를 선업합니다(아래에 문서화되어 있음) - 메소드 이름의 프리- 또는 포스트픽스을 "RPC"로 지정합니다 (대소문자 구별)
- 메소드 선언 앞에
[Rpc]
속성을 추가합니다 - RPC가 호출될 수 있는 위치와 실행되는 위치를 제어하기 위해
RpcSources
및RpcTargets
매개 변수를 구성합니다.
C#
[Rpc(source: RpcSources.InputAuthority, target: RpcTargets.StateAuthority)]
public void RPC_Configure(string name, Color color){
playerName = name;
playerColor = color;
}
노트: RPC는 메소드 이름에 "rpc" 프리 또는 프리픽스가 있어야 합니다(대소문자 구분 없음).
정적 RPC
정적 RPC는 약간 다른 규칙을 갖고 있습니다:
RpcSources
와RpcTargets
파라미터를 무시하고- 메소드의 첫 번째 매개 변수는
NetworkRunner
여야 합니다. - 콜백 리시버가 특정
NetworkObject
에 바인딩되어 있지 않기 때문에 (NetworkBehaviour
만이 아니라) 모든SimulationBehaviour
에서 구현할 수 있습니다.
소스 및 대상 필터가 없기 때문에 임의 클라이언트에서 정적 RPC를 호출할 수 있으며 모든 클라이언트로 전송됩니다. 여전히 RPC를 특정 PlayerRef
("Targeted RPC" 참조)로 대상화하여 호출을 수신할 사람을 제어할 수 있습니다.
C#
[Rpc]
public static void Rpc_MyStaticRpc(NetworkRunner runner, int a) { }
RPC 속성 파라미터
소스 및 타겟
RpcSources
와 RpcTargets
는 필터입니다. RpcSources
는 RPC를 전송할 수 있는 피어를 정의하는 반면, RpcTargets
는 피어가 실행되는 피어를 정의합니다.
All
: 전송할 수 있음 / 세션 내의 모든 피어에 의해서 실행됨(서버 포함).Proxies
: 전송할 수 있음 / 객체에 대하여 입력 권한 또는 상태 권한을 갖고 있지 않는 피어에 의해서 실행됨.InputAuthority
: 전송할 수 있음 / 객체에 대한 입력 권한이 있는 피어에 의해서 실행됨StateAuthority
: 전송할 수 있음 / 객체에 대한 상태 권한이 있는 피어에 의해서 실행됨.
중요: RPC에는 명시적 상태가 없습니다. RpcTargets.All
로 설정하면 늦게 가입하는 클라이언트와 연결을 끊었다 다시 연결하는 클라이언트로 정보를 전달하지 않습니다. 따라서 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): 재시뮬레이션을 하는 동안 호출되지 않아야 하는 경우 true로 설정TickAligned
(기본값 true): 수신측이 에서 보낸 틱 이후까지 RPC 실행을 지연시키지 않으려면 false로 설정합니다.
C#
[Rpc (RpcSources.All, RpcTargets.All, InvokeLocal = true, InvokeResim = true, TickAligned = false )]
void RpcStartBoost(){
m_BoostAnim.StartBoostAnimation();
}
RPC 메소드 파라미터
허용된 데이터 파라미터
- 원시 타입
- byte, sbyte
- Int16, Int32, Int64
- UInt16, UInt32, UInt64
- float
- double
- float
- double
- 유니티 구조체 타입 (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
: 어떤 곳에서 틱이 전송되었는지.Source
: 어떤 플레이어(PlayerRef
)가 보냈는지.Channel
:Unreliable
또는Reliable
RPC로 보냈는지 여부.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
로 선언됩니다.
서버 vs 호스트 소스
ServerMode
에서 Fusion을 사용할 경우 서버에서 보낸 RPC에 포함된 RpcInfo.Source
는 서버가 플레이어가 아니기 때문에 PlayerRef.None
으로 설정됩니다.
그러나 HostMode
에서 Fusion을 사용하는 경우 호스트-클라이언트는 서버와 플레이어를 모두 실행합니다. 기본적으로 호스트가 보낸 모든 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
:RpcSendCullResult
열거형 값은 원격 피어에 대한 RPC 호출의 성공 또는 실패 원인을 나타냅니다.SendResult
:RpcSendResult
구조체에는 RPC 전송 작업에 대한 메타 정보가 들어 있습니다.Result
:RpcSendMessageResult
이 RPC 메시지 보내기 작업에 대한 결과 플래그입니다.MessageSize
: RPC 패키지 크기.Receivers
: 이 RPC 작업의 리시버로 포함된PlayerRef
의 컬렉션CulledReceivers
: 이 RPC 전송 작업에서 리시버로 제외되고 도태된PlayerRef
의 모음입니다.
노트: 이 정보는 전송 성공 또는 실패에 대한 정보가 아니라 호출 과 전송 작업의 결과일 뿐입니다.
C#
[Rpc]
public RpcInvokeInfo RpcFoo() {
// RPC action
return default;
}
public override void FixedUpdateNetwork() {
var info = RpcFoo();
Debug.Log(info);
}
대상 Rpc
RPC가 특정 플레이어의 컴퓨터에서 단독으로 실행되어야 하는 경우, 이른바 대상 RPC가 사용됩니다. 인스턴스 RPC와 정적 RPC는 모두 [RpcTarget]
속성 앞에 있는 PlayerRef
매개 변수를 추가하여 대상 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
과 다릅니다.