레퍼런스
모든 바인딩과, 무엇이 그것을 일으키는지, 그리고 무엇을 하지 않는지.
전부 Udonite.Binding 안에 있습니다.
모든 바인딩은 같은 모양입니다.
| 멤버 | 하는 일 |
|---|---|
Watch(control) |
지켜보기 시작. 이벤트만 일으킴 |
Bind(control, observable) |
거기에 더해 Observable도 맞춰 감 |
Poll() |
컨트롤을 읽음. Update에서 호출 |
Unbind() |
지켜보기를 멈추고 Observable을 놓음 |
Value |
Observable이 있든 없든 컨트롤이 지금 가진 값 |
규칙도 같습니다.
- 바인딩하는 순간 컨트롤에 씁니다. 디자이너가 남겨둔 것이 아니라 값을 보여준 상태로 시작합니다.
- 다시 바인딩하면 앞의 것을 대체합니다. 두 번 도는
Start에서도 하나입니다. - null 컨트롤이나 Observable은 무시합니다. 비헤이비어를 멈추지 않습니다.
- 이미 추가한 핸들러는 남습니다. 다시
Watch하거나Unbind해도 그렇습니다. 핸들러는 추가한 쪽의 것이지 컨트롤의 것이 아닙니다. 버리려면 이벤트 필드를 비우세요. - 이벤트를 일으키는 것은 플레이어의 변경뿐입니다. Observable에 대입해서 컨트롤을 움직여도 일어나지 않습니다.
지켜보는 컨트롤
Update에서 Poll()이 필요합니다.
SliderBinding
| 멤버 | |
|---|---|
Action<float> OnChanged |
플레이어가 손잡이를 움직였을 때 |
Bind(Slider, Observable<float>) |
양방향 |
float Value |
손잡이의 위치 |
ToggleBinding
| 멤버 | |
|---|---|
Action<bool> OnChanged |
플레이어가 눌렀을 때 |
Bind(Toggle, Observable<bool>) |
양방향 |
bool Value |
체크되어 있는지 |
InputBinding
| 멤버 | |
|---|---|
Action<string> OnChanged |
키를 누를 때마다 |
Action<string> OnEndEdit |
내용을 바꾼 채 필드를 떠났을 때 |
Action OnFocused |
편집을 시작했을 때 |
Bind(TMP_InputField, Observable<string>) |
양방향 |
string Value |
필드의 내용 |
OnChanged는 키를 누를 때마다 보고합니다. 살아 있는 라벨에 묶인 필드는 그래야 하니까요. 그걸 원하지 않으면 버튼을 눌렀을 때 Value를 한 번 읽으세요.
플레이어가 입력하는 도중에 Observable에 쓰면 캐럿이 끝으로 갑니다. 바인딩이 스스로 그러지는 않지만(폴링이 먼저 플레이어의 글자를 가져오고, 되쓰는 값은 같은 문자열입니다) 편집 중에 대입하는 코드는 그렇게 됩니다.
움직여지는 컨트롤
이벤트도 Poll()도 없습니다. Observable이 먹이를 주는 방법입니다.
TextBinding<T>
| 멤버 | |
|---|---|
Bind(TextMeshProUGUI, Observable<T>) |
값을 보여줌 |
Bind(TextMeshProUGUI, Observable<T>, prefix, suffix) |
앞뒤에 글자를 붙여서 |
Bind(label, score, "Score: ", "")나 Bind(label, health, "", " HP")처럼. null 값은 폴트가 아니라 빈 문자열로 보입니다.
ActiveBinding
| 멤버 | |
|---|---|
Bind(GameObject, Observable<bool>) |
true인 동안 표시 |
BindInverted(GameObject, Observable<bool>) |
false인 동안 표시 |
하나의 Observable에 둘을 묶으면 짝이 맞는 표지판이 됩니다.
숨겨진 오브젝트의 비헤이비어는 멈춥니다. 바인딩이 올라가 있는 오브젝트를 숨기면 그 Update가 멈추고, 거기 있는 Poll()도 같이 멈춥니다. 폴링하는 바인딩은 계속 켜져 있는 곳에 두세요.
FillBinding
| 멤버 | |
|---|---|
Bind(Image, Observable<float>) |
이미 0에서 1 사이인 값 |
Bind(Image, Observable<float>, min, max) |
직접 정한 범위의 값 |
범위가 바인딩의 일부인 이유는 fillAmount가 0에서 1인데 월드가 세는 것들은 대부분 그렇지 않기 때문입니다. 범위 밖은 잘리고, 비었거나 뒤집힌 범위는 0으로 나누는 대신 빈 그림이 됩니다.
fillAmount가 동작하려면 Image의 Type을 Filled로 두어야 합니다.
하지 않는 것과 그 이유
버튼. 클릭은 값이 아니라 사건입니다. Slider.value, Toggle.isOn, TMP_InputField.text는 언제든 읽히지만 "지난 프레임 이후 클릭됐는가"는 읽히지 않아서 폴링할 대상이 없습니다. 버튼은 여전히 인스펙터에서 공개 메서드에 연결해야 합니다.
URL 필드. VRCUrlInputField는 선택은 받으면서 포커스되지 않습니다. ActivateInputField()를 직접 불러도 isFocused가 false로 남는 것을 측정했습니다. VRChat은 자기 키보드로 글자를 넣기 때문에 에디터에서는 시험할 방법이 없습니다. VRChat이 안내하는 대로 인스펙터에서 OnEndEdit을 쓰세요.
행 목록. ObservableList<T>로 여러 행을 움직이려면 오브젝트를 만들고 없애야 하고, 월드에서는 VRCObjectPool과 소유권 판단이 따라옵니다. 그건 다른 패키지입니다.
핸들러가 예외를 던지면
Udon에서는 예외가 나면 그 세션 내내 비헤이비어가 멈추고, 하나만 잡아내고 다음으로 넘어갈 방법이 없습니다. 예외를 던진 핸들러는 남은 알림과 그 비헤이비어가 그다음에 했을 일까지 함께 끌고 내려갑니다. 핸들러는 값을 읽고 뭔가를 갱신하는 선에서 끝내세요.