リファレンス
すべてのバインディングと、何がそれを起こすか、そして何をしないか。
すべて 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 なのに対し、ワールドが数えるものはたいていそうではないからです。範囲の外は丸められ、空や逆向きの範囲はゼロ除算ではなく空の絵になります。
fillAmount を効かせるには Image の Type を Filled にしてください。
しないこと、とその理由
ボタン。 クリックは値ではなく出来事です。Slider.value、Toggle.isOn、TMP_InputField.text はいつでも読めますが、「前のフレームから今までにクリックされたか」は読めないので、ポーリングする対象がありません。ボタンは今もインスペクターで公開メソッドに配線する必要があります。
URL フィールド。 VRCUrlInputField は選択は受け取るのにフォーカスされません。ActivateInputField() を直接呼んでも isFocused が false のままであることを実測しました。VRChat は自前のキーボードから文字を流し込むので、エディタでは動かしようがありません。VRChat が案内しているとおり、インスペクターで OnEndEdit を使ってください。
行のリスト。 ObservableList<T> から行の集まりを動かすにはオブジェクトの生成と破棄が要り、ワールドでは VRCObjectPool と所有権の判断が要ります。それは別のパッケージです。
ハンドラが例外を投げたら
Udon では例外が起きるとそのセッションの間ビヘイビアが停止し、ひとつ分を捕まえて次へ進むことはできません。投げたハンドラは残りの通知と、そのビヘイビアがそのあとにするはずだったことをまとめて道連れにします。ハンドラは値を読んで何かを更新するだけに留めてください。