Skip to content

Instantly share code, notes, and snippets.

@su10
Last active June 15, 2017 11:03
Show Gist options
  • Save su10/7428d104c45d04b0f29aa20f200b1cee to your computer and use it in GitHub Desktop.
Save su10/7428d104c45d04b0f29aa20f200b1cee to your computer and use it in GitHub Desktop.
UniRx入門 ~ データバインディングとUnityイベント関数の購読 ~ ref: http://qiita.com/su10/items/6d7fd792d4b553454a4f
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UniRx;
public class DataBindingSample1 : MonoBehaviour
{
// NOTE: newするときに初期値を与えることが可能
public ReactiveProperty<int> _intProperty = new ReactiveProperty<int>(1);
public ReactiveProperty<float> _floatProperty = new ReactiveProperty<float>(0.1f);
public ReactiveProperty<bool> _boolProperty = new ReactiveProperty<bool>(true);
public ReactiveProperty<string> _stringProperty = new ReactiveProperty<string>("ABC");
[SerializeField]
private Text[] _texts;
void Start()
{
// バインド(購読)する
_intProperty.SubscribeToText(_texts[0]);
_floatProperty.SubscribeToText(_texts[1]);
_boolProperty.SubscribeToText(_texts[2]);
_stringProperty.SubscribeToText(_texts[3]);
}
void Update()
{
// それぞれの値を適当に更新してみる
_intProperty.Value++;
_floatProperty.Value += 0.1f;
_boolProperty.Value = !_boolProperty.Value;
_stringProperty.Value += "a";
}
}
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UniRx;
public class DataBindingSample2 : MonoBehaviour
{
// NOTE: ジェネリックを使っていないので値をInspectorからセットできる
public IntReactiveProperty _intProperty = new IntReactiveProperty();
public FloatReactiveProperty _floatProperty = new FloatReactiveProperty();
public BoolReactiveProperty _boolProperty = new BoolReactiveProperty();
public StringReactiveProperty _stringProperty = new StringReactiveProperty();
[SerializeField]
private Text[] _texts;
[SerializeField]
private Button _button;
void Start()
{
// バインド(購読)する
_intProperty.Subscribe(value => _texts[0].text = value.ToString("D5"));
_floatProperty.Subscribe(value => _texts[1].text = (value * 10).ToString("F1"));
// NOTE: ButtonのInteractableにもバインドできる!
_boolProperty.SubscribeToInteractable(_button);
_stringProperty.Subscribe(value => _texts[3].text = value.Replace('a', 'z'));
}
void Update()
{
// それぞれの値を適当に更新してみる
_intProperty.Value++;
_floatProperty.Value += 0.1f;
_boolProperty.Value = !_boolProperty.Value;
_stringProperty.Value += "a";
}
}
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UniRx;
public class DataBindingSample3 : MonoBehaviour
{
#region private ReactiveProperty
[SerializeField]
private IntReactiveProperty _intProperty = new IntReactiveProperty();
[SerializeField]
private FloatReactiveProperty _floatProperty = new FloatReactiveProperty();
[SerializeField]
private BoolReactiveProperty _boolProperty = new BoolReactiveProperty();
[SerializeField]
private StringReactiveProperty _stringProperty = new StringReactiveProperty();
#endregion
#region public IReadOnlyReactiveProperty
public IReadOnlyReactiveProperty<int> IntProperty {
get { return _intProperty; }
}
public IReadOnlyReactiveProperty<float> FloatProperty {
get { return _floatProperty; }
}
public IReadOnlyReactiveProperty<bool> BoolProperty {
get { return _boolProperty; }
}
public IReadOnlyReactiveProperty<string> StringProperty {
get { return _stringProperty; }
}
#endregion
[SerializeField]
private Text[] _texts;
[SerializeField]
private Button _button;
void Update()
{
// それぞれの値を適当に更新してみる
_intProperty.Value++;
_floatProperty.Value += 0.1f;
_boolProperty.Value = !_boolProperty.Value;
_stringProperty.Value += "a";
}
}
using UniRx;
Observable.EveryApplicationPause()
.Subscribe(pause => Debug.Log("pause:" + pause))
.AddTo(this) // MonoBehaviourで使う時はこれを書いておくと良い
public interface IReadOnlyReactiveProperty<T> : IObservable<T>
{
T Value { get; }
bool HasValue { get; }
}
public interface IReactiveProperty<T> : IReadOnlyReactiveProperty<T>
{
new T Value { get; set; }
}
public class ReactiveProperty<T> : IReactiveProperty<T>, IDisposable, IOptimizedObservable<T>
{
// 実装
}
var trigger = gameObject.AddComponent<ObservableEventTrigger>();
trigger.OnPointerClickAsObservable()
.Subscribe(e => Debug.Log("OnPointerClick"));
var trigger = gameObject.AddComponent<ObservableEventTrigger>();
trigger.OnPointerClickAsObservable()
.Subscribe(e => Debug.Log("OnPointerClick"));
using UniRx;
// AsObservable()での変換だと初期値は購読時に送られてこない
button.OnClick.AsObservable()
toggle.OnValueChanged.AsObservable()
scrollbar.OnValueChanged.AsObservable()
scrollRect.OnValueChanged.AsObservable()
slider.OnValueChanged.AsObservable()
inputField.OnEndEdit.AsObservable()
inputField.OnValueChanged.AsObservable()
// 初期値が購読時に送られてくるver.
button.OnClickAsObservable()
toggle.OnValueChangedAsObservable()
scrollbar.OnValueChangedAsObservable()
scrollRect.OnValueChangedAsObservable()
slider.OnValueChangedAsObservable()
inputField.OnEndEditAsObservable()
inputField.OnValueChangedAsObservable()
using System;
using UnityEngine;
using UniRx;
using UniRx.Triggers;
public class Player : MonoBehaviour
{
public BoolReactiveProperty IsPoisoned = new BoolReactiveProperty();
public IntReactiveProperty Hp = new IntReactiveProperty();
public ReadOnlyReactiveProperty<bool> IsDead;
void Awake()
{
Hp.Value = 100;
// getterを作るような感じで新しいReactivePropertyを作れる
IsDead = Hp.Select(x => x <= 0).ToReadOnlyReactiveProperty();
}
void Start()
{
this.IsPoisoned
.Where(value => value) // trueに変化したときだけ通知
.Take(1)
.SelectMany(_ => Observable.Interval(TimeSpan.FromSeconds(1))) // 1秒ごとのタイマーに差し替え
.Take(10) // 10個来たら終わり
.TakeWhile(_ => IsPoisoned.Value && !IsDead.Value) // どちらかがtrueで終わり
.DoOnCompleted(() => IsPoisoned.Value = false)
.RepeatUntilDestroy(this) // 1回の毒が終わったら最初から購読し直し
.Subscribe(_ => Hp.Value -= 1);
}
}
using System;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
namespace UniRx
{
public static partial class UnityUIComponentExtensions
{
public static IDisposable SubscribeToText(this IObservable<string> source, TextMeshProUGUI text)
{
return source.SubscribeWithState(text, (x, t) => t.text = x);
}
public static IDisposable SubscribeToText<T>(this IObservable<T> source, TextMeshProUGUI text)
{
return source.SubscribeWithState(text, (x, t) => t.text = x.ToString());
}
public static IDisposable SubscribeToText<T>(this IObservable<T> source, TextMeshProUGUI text, Func<T, string> selector)
{
return source.SubscribeWithState2(text, selector, (x, t, s) => t.text = s(x));
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment