네트워크

동기화 필드, 커스텀 이벤트, 타입이 있는 네트워크 이벤트, 그리고 NetworkTransform 컴포넌트.

업데이트 2026-09-03

Udonite는 내부적으로 VRChat 자체의 네트워크 기능을 사용합니다. 규칙은 일반적인 Udon behaviour와 같습니다. GameObject의 동기화 상태를 쓸 수 있는 것은 그 소유자뿐이고, 네트워크 너머로 호출할 수 있는 것은 public 메서드뿐입니다.

동기화 필드

필드에 [UdonSynced]를 붙이고 behaviour의 동기화 모드를 설정합니다.

using Udonite.Package.Runtime;
using UnityEngine;
using VRC.SDKBase;
using VRC.Udon.Common;

[UdonBehaviourSyncMode(BehaviourSyncMode.Manual)]
public class Counter : UdoniteBehaviour
{
    [UdonSynced] public int count;

    public override void Interact()
    {
        if (!Networking.IsOwner(gameObject))
            Networking.SetOwner(Networking.LocalPlayer, gameObject);

        count = count + 1;
        this.RequestSerialization();
    }

    public override void OnDeserialization(DeserializationResult result)
    {
        Debug.Log("count is now " + count);
    }
}
  • BehaviourSyncMode.Manualthis.RequestSerialization()을 호출할 때 보냅니다. Continuous는 알아서 보내고, None은 아무것도 동기화하지 않습니다.
  • [UdonSynced(UdonSyncMode.Linear)]Smooth는 받는 쪽에서 숫자 필드를 보간합니다.
  • OnPreSerialization, OnPostSerialization, OnDeserialization이 전송 전후에 호출됩니다.

변경에 반응하기

[FieldChangeCallback]은 속성 이름을 지정합니다. 그 필드의 동기화된 값이 도착할 때마다 해당 속성의 setter가 실행됩니다.

[UdonSynced, FieldChangeCallback(nameof(Lit))]
private bool lit;

public bool Lit
{
    get => lit;
    set
    {
        lit = value;
        lamp.SetActive(value);
    }
}

속성의 형식은 필드의 형식과 정확히 같아야 합니다.

커스텀 이벤트

public 메서드는 이름을 지정해 다른 클라이언트로 보낼 수 있습니다.

this.SendCustomNetworkEvent(NetworkEventTarget.All, nameof(Ring));

public void Ring()
{
    bell.Play();
}

NetworkEventTarget.Owner는 그 오브젝트의 소유자에게만 보냅니다. SendCustomEventDelayedSecondsSendCustomEventDelayedFrames는 로컬 호출을 나중으로 미룹니다.

타입이 있는 네트워크 이벤트

구조가 있는 페이로드를 보내려면 SerializeDeserialize 쌍을 가진 이벤트 클래스를 정의하고, 받는 behaviour에 핸들러를 둡니다.

using Udonite.Package.Runtime;
using UnityEngine;

public class ScoreEvent : NetworkEvent
{
    public int player;
    public int score;

    public void Serialize(ByteWriter writer)
    {
        writer.WriteInt32(player);
        writer.WriteInt32(score);
    }

    public void Deserialize(ByteReader reader)
    {
        player = reader.ReadInt32();
        score = reader.ReadInt32();
    }
}

public class Scoreboard : UdoniteBehaviour
{
    public void Award(int player, int score)
    {
        ScoreEvent evt = new ScoreEvent();
        evt.player = player;
        evt.score = score;
        Udonite.Network.Send(evt, this);
    }

    [NetworkEventHandler]
    public void OnScore(ScoreEvent evt)
    {
        Debug.Log("player " + evt.player + " scored " + evt.score);
    }
}

Udonite.Network.Send(evt, receiver)는 이벤트를 직렬화해, 모든 클라이언트에서 receiver에 있는 그 이벤트 형식을 매개변수로 받는 [NetworkEventHandler] 메서드로 전달합니다. 반드시 정규화된 이름으로 쓰세요. using UnityEngine;이 있는 범위에서는 그냥 Network라고 쓰면 Unity의 사용 중단된 UnityEngine.Network와 충돌합니다. 내용은 동기화 필드로 운반되므로, receiver의 GameObject 소유자가 호출할 때만 다른 클라이언트에 도달합니다.

NetworkTransform

NetworkTransform은 위치, 회전, 크기를 보간과 순간이동 감지와 함께 동기화해 주는, 바로 쓸 수 있는 behaviour입니다. 오브젝트에 추가하고 컴파일한 뒤 움직이기만 하면 됩니다. 같은 오브젝트에 VRC_Pickup이 있으면, 집을 때 소유권을 가져오고 놓을 때 멈춘 자세를 보냅니다. 전송 빈도, 채널별 임계값, 순간이동 판정 거리는 인스펙터 필드입니다.

소유권

OnOwnershipRequest를 재정의해 false를 반환하면 이전을 거부할 수 있습니다. OnOwnershipTransferred는 소유자가 바뀔 때 모든 클라이언트에서 호출됩니다. ClientSim은 소유권 요청을 발생시키지 않으므로, 그 부분은 업로드한 월드에서 테스트하세요.

Something went wrong. Reload