레퍼런스

Observable, ObservableList, ObservableDictionary의 모든 멤버와 각각이 무엇을 알리는지.

업데이트 2026-09-08

전부 Udonite.Observables 안에 있습니다.

Observable<T>

new Observable<int>()        // 기본값, 아무에게도 알리지 않음
new Observable<int>(7)       // 초기값 지정, 아무에게도 알리지 않음
멤버 알림
T Value { get; set; } 설정할 때, 값이 다를 때만
Subscribe(Action<T> handler) 안 함
Subscribe(Action<T> handler, bool notifyNow) notifyNow이 핸들러만 호출
Unsubscribe(Action<T> handler) 안 함. 구독하지 않은 것을 빼도 아무 일도 없음
UnsubscribeAll() 안 함
SetSilently(T value) 안 함
Publish() 함. 바뀌었든 아니든 모든 구독자
bool CascadeStalled { get; } 안 함
ToString() 안 함. 값, 값이 없으면 ""

동등성은 object.Equals입니다. 같은 문자열 둘은 변경이 아닙니다. null도 다른 값과 마찬가지라서 null에서 null은 조용하고, null에서 값으로 가는 것은 그렇지 않습니다.

두 번 구독해도 한 번입니다. 보통 Start가 다시 실행되면서 그렇게 되는데, 변경마다 두 번 불리는 것은 언제나 버그입니다.

구독자는 어디에 있어도 됩니다. score.Subscribe(display.Show)는 다른 비헤이비어의 핸들러에 닿고, score.Subscribe(OnChanged)는 이 비헤이비어의 핸들러에 닿습니다. 비헤이비어가 아닌 클래스는 자기 안에서 자기 메서드를 구독합니다. 하나의 Observable이 이 세 가지를 섞어서 들고 있을 수 있습니다.

예외는 비헤이비어가 아닌 다른 객체의 메서드를 건네는 경우입니다. tally가 평범한 클래스일 때의 score.Subscribe(tally.Add)는 Udon에 리시버를 둘 자리가 없어서 거부됩니다. 그 클래스가 스스로 구독하게 하세요.

public class Tally
{
    public void Watch(Observable<int> score) { score.Subscribe(Add); }

    private void Add(int value) { ... }
}

구독자 수는 없고 Unsubscribe는 아무것도 알려주지 않습니다. 제거는 내용으로 맞추므로 추가할 때 쓴 값이 아니라 그 자리에서 새로 만든 델리게이트로도 뺄 수 있습니다. 다만 Udon에는 구독자 목록을 들여다볼 수단이 등록되어 있지 않습니다. 무엇을 구독했는지 알아야 하는 코드는 스스로 기록해 두세요.

CascadeStalled는 열여섯 번 다시 시작하고도 가라앉지 않은 publish를 알립니다. 거기까지 가려면 같은 옵저버블에 되쓰는 구독자가 있어야 하고 컴파일러가 그걸 거부하므로, 월드에서는 false 그대로입니다.

ObservableList<T>

구독자는 Action<ObservableList<T>>를 받고 리스트 자체를 건네받습니다.

멤버 알림 LastChange
T this[int] { get; set; } 설정할 때, 다를 때만 Replaced
Add(T) Added
AddRange(T[]) 범위 전체에 한 번. 비었거나 null이면 없음 None
Insert(int, T) Added
bool Remove(T) 있었을 때만 Removed
RemoveAt(int) Removed
Clear() 뭔가 들어 있었을 때만 Cleared
AddSilently(T) 안 함
Contains, IndexOf, ToArray, Count 안 함

핸들러 안에서는 LastChange, LastIndex, LastItem이 무슨 일이 있었는지 알려 주므로, 구독자는 전부 다시 만들지 않고 오브젝트 하나만 띄우면 됩니다.

private void OnNamesChanged(ObservableList<string> list)
{
    if (list.LastChange == CollectionChange.Added)
        Spawn(list.LastItem);
    else
        RedrawEverything(list);
}

이 값들은 진행 중인 알림을 설명하며, 핸들러 안에서만 의미가 있습니다.

ObservableDictionary<TKey, TValue>

구독자는 Action<ObservableDictionary<TKey, TValue>>를 받습니다.

멤버 알림 LastChange
TValue this[TKey] { get; } 안 함
Set(TKey, TValue) 값이 다를 때만 새 키면 Added, 이미 있던 키면 Replaced
bool Remove(TKey) 있었을 때만 Removed
Clear() 뭔가 들어 있었을 때만 Cleared
SetSilently(TKey, TValue) 안 함
ContainsKey, TryGetValue, Count 안 함

LastKeyLastValue가 무엇이 바뀌었는지 알려 줍니다.

인덱서 세터는 일부러 없습니다. Udon에서 딕셔너리는 DataDictionary이고, 없는 키를 읽으면 기본값을 돌려주는 대신 폴트가 납니다. 세터 안에 숨은 읽기는 함정이 되므로, Set은 읽기를 밖으로 드러냅니다. 먼저 ContainsKey로 묻거나 TryGetValue를 쓰세요.

CollectionChange

None, Added, Removed, Replaced, Cleared.

None은 "아직 아무 일도 없었음"이면서 동시에 "단일 항목이 없는 일괄 변경"입니다. AddRange가 그렇고, 변경을 보고하는 대신 컬렉션을 보여 주는 Subscribe(handler, true)가 그렇습니다.

핸들러가 예외를 던지면

Udon에서는 예외가 나면 그 세션 내내 behaviour가 멈추고, 구독자 하나 것만 잡아내고 다음으로 넘어갈 방법이 없습니다. 예외를 던진 핸들러는 남은 알림과 그 behaviour가 그다음에 했을 일까지 함께 끌고 내려갑니다. 핸들러는 값을 읽고 뭔가를 갱신하는 선에서 끝내세요.

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