Remote Procedure Calls (PRC) - cheona-thousand-man/Unity-myBasics-Wiki GitHub Wiki

๊ฐœ์š”

  • ์›๊ฒฉ ํ”„๋กœ์‹œ์ € ํ˜ธ์ถœ(RPC) ๊ฒŒ์ž„ ์ด๋ฒคํŠธ๋ฅผ ๊ณต์œ ํ•˜๋Š” ๋ฐ ์ ํ•ฉ
  • Input Struct์™€ [Networked] ์†์„ฑ ์ง€์†์ ์œผ๋กœ ๋ณ€ํ™”ํ•˜๋Š” ๋„คํŠธ์›Œํฌ ํด๋ผ์ด์–ธํŠธ ๊ฐ„์˜ ์ƒํƒœ๋ฅผ ๊ณต์œ ํ•˜๋Š” ๋ฐ ์ ํ•ฉ

์˜ˆ๋ฅผ ๋“ค์–ด ํ”Œ๋ ˆ์ด์–ด๊ฐ€ ์ธ๋ฒคํ† ๋ฆฌ์—์„œ ํŠน์ • ํ‚ค๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ž ๊ธด ๋ฌธ์„ ์—ฌ๋Š” ๋“œ๋ฌธ ๋ณต์žกํ•œ ์ƒํ˜ธ์ž‘์šฉ์„ ์ˆ˜ํ–‰ํ•˜๊ณ ์ž ํ•  ๋•Œ,

  • ์ด๋ฅผ Input Authority๊ฐ€ ์—†๋Š” ๊ฐ์ฒด์™€ ์ƒํ˜ธ์ž‘์šฉํ•˜๋Š” ๊ฒฝ์šฐ์— RPC๊ฐ€ ์ ํ•ฉ
    • Input Struct์— ์ถ”๊ฐ€ ํ•„๋“œ๋ฅผ ํฌํ•จ์‹œ์ผœ ์ด๋Ÿฌํ•œ ์ž‘์—…์„ ๊ธฐ์ˆ ์ ์œผ๋กœ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ์ด๋Š” Input Struct ๊ตฌ์กฐ ๋ณต์žกํ™”
    • Input Struct๋Š” ์‹ ๋ขฐํ•  ์ˆ˜ ์—†๋Š” ๋ฉ”์‹œ์ง€๋กœ ์ „์†ก๋˜๋ฉฐ, ํ”Œ๋ ˆ์ด์–ด๊ฐ€ ๊ธฐ๋Œ€ํ•˜๋Š” ๋‹จ์ผ ์ผํšŒ์„ฑ ์ž‘์—…์— ์˜ํ–ฅO (์ง€์†์ ์ธ ์ž…๋ ฅ(์˜ˆ: ์บ๋ฆญํ„ฐ ์ด๋™)์—๋Š” ํฐ ๋ฌธ์ œX)

Setup

  • ์ธ์Šคํ„ด์Šค RPC
  • ์ •์  RPC
  • ๋Œ€์ƒ ์ง€์ • RPC

Instance RPC

NetworkObject์˜ NetworkBehaviour์—์„œ RPC ์ •์˜

  1. void ๋˜๋Š” RpcInvokeInfo ๋ฐ˜ํ™˜ ํ˜•์‹์˜ ์ผ๋ฐ˜ C# ๋ฉ”์„œ๋“œ ์„ ์–ธ
  2. ๋ฉ”์„œ๋“œ ์ด๋ฆ„ ์•ž์ด๋‚˜ ๋’ค์— RPC ์ถ”๊ฐ€(๋Œ€์†Œ๋ฌธ์ž ๊ตฌ๋ถ„ ์—†์Œ)
  3. ๋ฉ”์„œ๋“œ ์„ ์–ธ ์•ž์— [Rpc] ์†์„ฑ์„ ์ถ”๊ฐ€
  4. RpcSources ๋ฐ RpcTargets ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๊ตฌ์„ฑํ•˜์—ฌ RPC๋ฅผ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋Š” ์œ„์น˜์™€ ์‹คํ–‰๋˜๋Š” ์œ„์น˜ ์ œ์–ด
[Rpc(sources: RpcSources.InputAuthority, targets: RpcTargets.StateAuthority)]
public void RPC_Configure(string name, Color color, RpcInfo info = default){
    playerName = name;
    playerColor = color;
}

Static RPC

์•ฝ๊ฐ„ ๋‹ค๋ฅธ ๊ทœ์น™ ์ค€์ˆ˜

  1. RpcSources ๋ฐ RpcTargets ๋งค๊ฐœ๋ณ€์ˆ˜ ๋ฌด์‹œ
  2. ๋ฉ”์„œ๋“œ์˜ ์ฒซ ๋ฒˆ์งธ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ NetworkRunner ์š”๊ตฌ
  3. ํŠน์ • NetworkObject์— ๋ฐ”์ธ๋”ฉ๋˜์ง€ ์•Š์œผ๋ฏ€๋กœ SimulationBehaviour์— ๊ตฌํ˜„ ๊ฐ€๋Šฅ
[Rpc]
public static void Rpc_MyStaticRpc(NetworkRunner runner, int a) { }

RPC ์†์„ฑ ๋งค๊ฐœ๋ณ€์ˆ˜ (ํ•„์ˆ˜)

  1. RpcSources RPC๋ฅผ ๋ณด๋‚ผ ์ˆ˜ ์žˆ๋Š” Peer๋ฅผ ์ •์˜
  2. RpcTargets ์‹คํ–‰๋˜๋Š” Peer๋ฅผ ์ •์˜
  • All ์„ธ์…˜์˜ ๋ชจ๋“  ํ”ผ์–ด(์„œ๋ฒ„ ํฌํ•จ)๊ฐ€ ๋ณด๋‚ผ ์ˆ˜ ์žˆ์œผ๋ฉฐ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.
  • Proxies ๊ฐ์ฒด์— Input Authority ๋˜๋Š” State Authority๊ฐ€ ์—†๋Š” ํ”ผ์–ด๊ฐ€ ๋ณด๋‚ผ ์ˆ˜ ์žˆ์œผ๋ฉฐ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.
  • InputAuthority ๊ฐ์ฒด์— Input Authority๊ฐ€ ์žˆ๋Š” ํ”ผ์–ด๊ฐ€ ๋ณด๋‚ผ ์ˆ˜ ์žˆ์œผ๋ฉฐ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.
  • StateAuthority ๊ฐ์ฒด์— State Authority๊ฐ€ ์žˆ๋Š” ํ”ผ์–ด๊ฐ€ ๋ณด๋‚ผ ์ˆ˜ ์žˆ์œผ๋ฉฐ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

RPC์—๋Š” ๋ช…์‹œ์ ์ธ ์ƒํƒœ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ๋‚˜์ค‘์— ์ฐธ๊ฐ€ํ•œ ํด๋ผ์ด์–ธํŠธ์™€ ์—ฐ๊ฒฐ์ด ๋Š๊ฒผ๋‹ค๊ฐ€ ๋‹ค์‹œ ์—ฐ๊ฒฐ๋œ ํด๋ผ์ด์–ธํŠธ๋Š” RPC๊ฐ€ ๋ฐœ์ƒํ•œ ์‚ฌ์‹ค์„ ์žŠ์–ด๋ฒ„๋ฆฝ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ 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;
    }
}

์„ ํƒ์  RPC ์†์„ฑ ๋งค๊ฐœ๋ณ€์ˆ˜

  • Channel(๊ธฐ๋ณธ๊ฐ’ Reliable) RPC๊ฐ€ ์ „์†ก ์ค‘ ์†์‹ค๋  ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ Unreliable๋กœ ์„ค์ •
  • InvokeLocal(๊ธฐ๋ณธ๊ฐ’ true) RPC๊ฐ€ ๋กœ์ปฌ ํด๋ผ์ด์–ธํŠธ์—์„œ ํ˜ธ์ถœ๋ ์ง€ ์—ฌ๋ถ€
  • InvokeResim(๊ธฐ๋ณธ๊ฐ’ false) ์žฌ์‹œ๋ฎฌ๋ ˆ์ด์…˜ ์ค‘์— RPC๊ฐ€ ํ˜ธ์ถœ๋ ์ง€ ์—ฌ๋ถ€
  • TickAligned(๊ธฐ๋ณธ๊ฐ’ true) RPC๊ฐ€ ์ „์†ก๋œ ํ‹ฑ์—์„œ ๋˜๋Š” ์ดํ›„์— RPC๋ฅผ ์‹คํ–‰ํ• ์ง€ ์—ฌ๋ถ€ ์„ค์ •
[Rpc (RpcSources.All, RpcTargets.All, InvokeLocal = true, InvokeResim = true, TickAligned = false )]
void RpcStartBoost(){
    m_BoostAnim.StartBoostAnimation();
}

RPC ๋ฉ”์„œ๋“œ ๋งค๊ฐœ๋ณ€์ˆ˜

RPC๋Š” ๋Ÿฐํƒ€์ž„์— ์ง๋ ฌํ™”๋˜๋ฏ€๋กœ ์ผ๋ฐ˜์ ์ธ CLR ํƒ€์ž…(e.g.: bool)์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด Fusion ํŠน์œ ์˜ ํƒ€์ž…(e.g. NetworkBool)๋ณด๋‹ค ๊ถŒ์žฅ

ํ—ˆ์šฉ๋˜๋Š” ๋ฐ์ดํ„ฐ ๋งค๊ฐœ๋ณ€์ˆ˜

  • ์›์‹œ ํƒ€์ž… byte, sbyte, Int16, Int32, Int64, UInt16, UInt32, UInt64, float, double
  • Unity ๊ตฌ์กฐ์ฒด ํƒ€์ž… Vector2, Vector3, Vector4, Quaternion, Matrix4x4, Vector2Int, Vector3Int, BoundingSphere, Bounds, Rect, BoundsInt, RectInt, Color, Color32
  • System.Guid
  • ์‚ฌ์šฉ์ž ์ •์˜ INetworkStructs
  • Fusion ์ •์˜ INetworkStructs NetworkString, NetworkBool, Ptr, Angle, BitSet64, BitSet128, BitSet192, BitSet256, PlayerRefSet, NetworkId, NetworkButtons, NetworkRNG, NetworkObjectGuid, NetworkObjectHeader, NetworkPrefabRef, NetworkPrefabId, SceneRef, TickTimer, IFixedStorage (_2, _4, _8, _16, _32, _64, _128, _256, _512)
  • Fusion ํƒ€์ž… NetworkObject (NetworkId๋กœ ์ง๋ ฌํ™”๋จ), NetworkBehaviour (NetworkId์™€ NetworkBehaviour ์ธ๋ฑ์Šค๋กœ ์ง๋ ฌํ™”๋จ), PlayerRef (PlayerRef.PlayerId๋กœ ์ง๋ ฌํ™”๋จ)
  • String
  • ์œ„์— ๋‚˜์—ด๋œ ํƒ€์ž…์˜ ๋ฐฐ์—ด

RpcInfo (์„ ํƒ)

RPC ๋ฉ”์„œ๋“œ ์„ ์–ธ์—์„œ RPC ๋ฉ”ํƒ€ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•˜๋Š” RpcInfo ์‚ฌ์šฉ ๊ฐ€๋Šฅ

  • Tick ์ „์†ก๋œ Tick
  • Source ์ด๋ฅผ ๋ณด๋‚ธ ํ”Œ๋ ˆ์ด์–ด(PlayerRef)
  • Channel Unreliable ๋˜๋Š” Reliable๋กœ ์ „์†ก๋˜์—ˆ๋Š”์ง€ ์—ฌ๋ถ€
  • IsInvokeLocal ์ด RPC๋ฅผ ๋กœ์ปฌ ํ”Œ๋ ˆ์ด์–ด๊ฐ€ ํ˜ธ์ถœํ–ˆ๋Š”์ง€ ์—ฌ๋ถ€
[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๋กœ ์„ ์–ธ

Server vs Host Source

  1. [Server Mode] ์„œ๋ฒ„์—์„œ ๋ณด๋‚ธ RPC์— ํฌํ•จ๋œ RpcInfo.Source๋Š” PlayerRef.None์œผ๋กœ ์„ค์ •
  2. [Host Mode]
    1. ํ˜ธ์ŠคํŠธ-ํด๋ผ์ด์–ธํŠธ๋Š” ์„œ๋ฒ„์™€ ํ”Œ๋ ˆ์ด์–ด ๋‘˜ ๋‹ค ์‹คํ–‰
    2. ๊ธฐ๋ณธ์ ์œผ๋กœ ํ˜ธ์ŠคํŠธ๊ฐ€ ๋ณด๋‚ธ RPC๋Š” ์„œ๋ฒ„์™€ ๋™์ผํ•˜๊ฒŒ ์ž‘๋™ํ•˜์—ฌ RpcInfo.Source๋ฅผ PlayerRef.None์œผ๋กœ ์„ค์ •
    3. ํ˜ธ์ŠคํŠธ์˜ ๋กœ์ปฌ PlayerRef๋ฅผ ํฌํ•จํ•˜๋ ค๋ฉด HostMode ์†์„ฑ์„ RpcHostMode.SourceIsHostPlayer๋กœ ์„ค์ •

HostMode๋Š” ๋‹ค์Œ ๋‘ ๋ชจ๋“œ ์ค‘ ํ•˜๋‚˜๋กœ ์„ค์ •

  • RpcHostMode.SourceIsServer (๊ธฐ๋ณธ๊ฐ’) RpcInfo.Source๊ฐ€ PlayerRef.None์œผ๋กœ ์„ค์ •
  • RpcHostMode.SourceIsHostPlayer Fusion์ด HostMode๋กœ ์‹คํ–‰๋  ๋•Œ RpcInfo.Source๊ฐ€ ๋กœ์ปฌ PlayerRef๋กœ ์„ค์ •

ํ˜ธ์ŠคํŠธ์˜ PlayerRef๋ฅผ RpcSource.Info์— ํฌํ•จํ•˜๊ธฐ ์œ„ํ•ด ์ด์ „ ์ฝ”๋“œ๋ฅผ ์˜ˆ์‹œ์™€ ๊ฐ™์ด ์ˆ˜์ •

[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 ๋ฉ”์„œ๋“œ๋Š” ๋ฐ˜ํ™˜๊ฐ’์œผ๋กœ RPC ํ˜ธ์ถœ ๋ฐ ์ „์†ก ์ž‘์—…์— ๋Œ€ํ•œ ์ •๋ณด๊ฐ€ ๋‹ด๊ธด RpcInvokeInfo๋ฅผ ๋ฐ˜ํ™˜ ๊ฐ’์œผ๋กœ ์ •์˜ ๊ฐ€๋Šฅ

  • LocalInvokeResult ๋กœ์ปฌ ํ˜ธ์ถœ ์ž‘์—…์˜ ์„ฑ๊ณต ์—ฌ๋ถ€ ๋˜๋Š” ์‹คํŒจ ์›์ธ์„ ๋‚˜ํƒ€๋‚ด๋Š” RpcLocalInvokeResult ์—ด๊ฑฐํ˜• ๊ฐ’
  • SendCullResult ์›๊ฒฉ ํ”ผ์–ด์— ๋Œ€ํ•œ RPC ํ˜ธ์ถœ์˜ ์„ฑ๊ณต ์—ฌ๋ถ€ ๋˜๋Š” ์‹คํŒจ ์›์ธ์„ ๋‚˜ํƒ€๋‚ด๋Š” RpcSendCullResult ์—ด๊ฑฐํ˜• ๊ฐ’
  • SendResult RPC ์ „์†ก ์ž‘์—…์— ๋Œ€ํ•œ ๋ฉ”ํƒ€ ์ •๋ณด๋ฅผ ํฌํ•จํ•˜๋Š” RpcSendResult ๊ตฌ์กฐ์ฒด
  • Result RPC ๋ฉ”์‹œ์ง€ ์ „์†ก ์ž‘์—…์˜ ๊ฒฐ๊ณผ ํ”Œ๋ž˜๊ทธ๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” RpcSendMessageResult
  • MessageSize RPC ํŒจํ‚ค์ง€์˜ ํฌ๊ธฐ
  • Receivers ์ด RPC ์ž‘์—…์˜ ์ˆ˜์‹ ์ž๋กœ ํฌํ•จ๋œ PlayerRefs ์ปฌ๋ ‰์…˜
  • CulledReceivers ์ด RPC ์ „์†ก ์ž‘์—…์—์„œ ์ œ์™ธ๋œ PlayerRefs ์ปฌ๋ ‰์…˜

์ฐธ๊ณ : ์ด๋Š” ์ „์†ก ์„ฑ๊ณต ์—ฌ๋ถ€๋‚˜ ์‹คํŒจ ์—ฌ๋ถ€์— ๋Œ€ํ•œ ์ •๋ณด๊ฐ€ ์•„๋‹ˆ๋ผ, ํ˜ธ์ถœ ๋ฐ ์ „์†ก ์ž‘์—…์˜ ๊ฒฐ๊ณผ์— ๋Œ€ํ•œ ์ •๋ณด๋งŒ ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.

[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์„ ์ „๋‹ฌํ•˜๋ฉด ์„œ๋ฒ„๋ฅผ ๋Œ€์ƒ์œผ๋กœ ํ•ฉ๋‹ˆ๋‹ค!

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

์ค‘์š”: ๋ฉ”์„œ๋“œ ์„ ์–ธ ๋‚ด์—์„œ ์‚ฌ์šฉํ•˜๋Š” [RpcTarget] ์†์„ฑ์€ ๋ฉ”์„œ๋“œ ์„ ์–ธ ์•ž์— ์žˆ๋Š” [Rpc] ์†์„ฑ์˜ RpcTargets ๋งค๊ฐœ๋ณ€์ˆ˜์™€ ๋‹ค๋ฆ…๋‹ˆ๋‹ค.