동기화 값

모든 클라이언트가 가지는 변수, 그 안에 넣을 수 있는 것, 변화를 직접 알려야 하는 두 경우.

업데이트 2026-09-10

선언하기

동기화 값은 비헤이비어의 필드이거나, 원한다면 자동 프로퍼티입니다.

private Synced<int> score = new Synced<int>();

public Synced<string> Message { get; } = new Synced<string>();

둘 다 쓴 이름 그대로의 복제 변수 하나가 됩니다. 접근자를 직접 쓴 프로퍼티는 동작할 수 없어 거부됩니다. Udon 이 복제하는 것은 이름이 있는 변수이고, 접근자는 각 클라이언트에서 새로 실행되는 코드이기 때문입니다.

비헤이비어 위에 있어야 합니다. 비헤이비어가 쓰는 평범한 클래스에 둔 동기화 값은 컴파일은 되지만 복제되지 않으므로, 그것도 필드 이름을 대며 거부합니다.

넣을 수 있는 것

모든 C# 기본 형식, string, Vector2, Vector3, Vector4, Quaternion, Color, Color32, VRCUrl, 그리고 그 배열들. 이것은 이 패키지가 아니라 VRChat 의 목록입니다. 그 밖의 것은 실행 중에 조용히 빠지는 대신 컴파일할 때 거부됩니다.

시작 값은 생성자에 넣습니다.

private Synced<int> lives = new Synced<int>(3);

읽고 쓰기

score.Value = score.Value + 1;

쓰면 복제됩니다. 짝지어 불러야 할 직렬화 호출이 없으므로, 대입해 놓고 호출을 잊어 동기화가 조용히 멈추는 실패가 사라집니다. 한 프레임에 여러 번 써도 전송은 한 번입니다. VRChat 이 합쳐 보냅니다.

쓸 수 있는 쪽은 소유자뿐입니다. 다른 클라이언트에서의 대입은 그 자리에 남습니다. 이 패키지가 감추지 않는 유일한 Udon 규칙입니다. Ownership.Claim(gameObject) 으로 먼저 가져오거나, 애초에 알맞은 클라이언트가 소유한 오브젝트에 두세요.

변화 받기

score.Subscribe(OnScoreChanged);

값이 도착하면 쓴 클라이언트를 포함해 모두의 핸들러가 돕니다. 같은 핸들러를 두 번 구독해도 늘지 않고, Unsubscribe 로 뗍니다.

무엇에서 바뀌었는지도 필요한 핸들러는 둘 다 받습니다.

score.Subscribe(OnScoreChanged);

private void OnScoreChanged(int previous, int current)
{
    scoreboard.Show(current, current - previous);
}

첫 변화 이전에는 그 앞의 값이 없으므로 그 형식의 기본값입니다. 같은 값에 두 형태를 함께 구독할 수 있고, 둘 다 돕니다.

핸들러는 갱신이 전부 도착한 뒤에 돕니다. VRChat 은 한 번에 하나씩 적용하므로, 도착하는 대로 부르면 핸들러가 읽은 다른 값이 아직 이전 값일 수 있습니다. 두 클라이언트로 확인했습니다. 카운터가 도착한 옆에서 문자열은 아직 비어 있었습니다. 지금은 같은 갱신으로 들어온 값을 읽습니다.

배열

배열은 값 전체로 복제되므로 통째로 바꾸는 것은 기대대로 동작합니다.

private Synced<int[]> scores = new Synced<int[]>(new int[8]);

scores.Value = fresh;

원소 하나를 쓰는 것은 대입만으로는 컴파일러가 볼 수 없는 경우이니, 직접 알려주세요.

scores.Value[2] = 7;
scores.MarkChanged();

MarkChanged 는 배열을 통째로 대입했을 때와 똑같이 복제하고 이 클라이언트의 구독자에게도 알립니다. 없으면 변경은 쓴 클라이언트에 조용히 남습니다.

소유권

Ownership.IsMine(gameObject) 이 클라이언트가 그 오브젝트의 동기화 값을 쓸 수 있는지
Ownership.Claim(gameObject) 거부되지 않으면 가져오기
Ownership.GiveTo(player, gameObject) 누군가에게 넘기기
Ownership.Of(gameObject) 누가 가졌는지

OnOwnershipRequest 를 재정의해 false 를 돌려주면 이전을 거부할 수 있습니다. MasterOwned 는 그 재정의를 이미 써 둔 것입니다. 상속하면 조율하는 클라이언트만 그 오브젝트를 가질 수 있어, 다른 누구도 쓰지 못할 값을 둘 자리가 됩니다.

ClientSim 은 소유권 요청을 일으키지 않습니다. 이것만은 업로드한 월드에서 확인해야 합니다.

문제가 발생했습니다 새로 고침