文章目录
3.2 ReactiveProperty
ReactiveProperty 的值可以读写,并且在值变化时发行消息。即带有Observable功能的变数。
3.2.1 ReactiveProperty
值变化时发行OnNext消息。
Dispose()执行时,发行OnCompleted消息
- 基本使用例
using UniRx;
using UnityEngine;
namespace Sample.Section3.ReactiveProperty
{
public class ReactivePropertySample : MonoBehaviour
{
private void Start()
{
// int 型的ReactiveProperty
// 初期値是100
var health = new ReactiveProperty<int>(100);
// .Value 读取现在设定的值
Debug.Log("現在の値:" + health.Value);
// ReactiveProperty 可以直接被 Subscribe
// Subscribe 时 会发行当前设定的值的消息
health.Subscribe(
x => Debug.Log("现在通知值:" + x),
() => Debug.Log("OnCompleted"));
// .Value 赋值时 、发行OnNext 消息
health.Value = 50;
Debug.Log("现在的值:" + health.Value);
// Dispose()时发行 OnCompleted 消息
health.Dispose();
}
}
}
像这样每当ReactiveProperty 的Value属性更新时,发行OnNext消息
ReactiveProperty 的Value属性可以被读取,读取时是当时最新的值
-
强制发行消息
ReactiveProperty 的Value属性更新时,如果更新的值和上一个值相同,不会发行消息,如果想要强制将值发行需要使用SetValueAndForceNotify()
using UnityEngine; using UniRx; namespace Sample.Section3.ReactiveProperty { public class ReactivePropertySample2 : MonoBehaviour { private void Start() { var health = new ReactiveProperty<int>(100); health .Subscribe(x => Debug.Log("通知的值:" + x)); // x Debug.Log("<Value = 100>"); health.Value = 100; // 强制发行消息使用SetValueAndForceNotify Debug.Log("<Value 强制更新>"); health.SetValueAndForceNotify(100); health.Dispose(); } } }
-
跳过想要发行的消息
当不想要发行某消息时 可以使用SkipLatestValueOnSubscribe()
using UnityEngine; using UniRx; namespace Sample.Section3.ReactiveProperty { public class ReactivePropertySample3 : MonoBehaviour { private void Start() { var health = new ReactiveProperty<int>(100); health // Subscribe()后的无视OnNext消息 .SkipLatestValueOnSubscribe() .Subscribe(x => Debug.Log("通知的值:" + x)); health.Value = 50; health.Dispose(); } } }
-
ReactiveProperty 的值在编辑器上设定
ReactiveProperty 不能在编辑器上设定值,如果想要设定,可以只用类型明确的IntReactiveProperty 的类型
using UnityEngine; using UniRx; namespace Sample.Section3.ReactiveProperty { public class ReactivePropertyOnInspectorWindow : MonoBehaviour { // 不会表示 public ReactiveProperty<int> A; // 会表示 public IntReactiveProperty B; //其他的各种类型 public LongReactiveProperty C1; public ByteReactiveProperty C2; public FloatReactiveProperty C3; public DoubleReactiveProperty C4; public StringReactiveProperty C5; public BoolReactiveProperty C6; public Vector2ReactiveProperty C7; public Vector3ReactiveProperty C8; public Vector4ReactiveProperty C9; public ColorReactiveProperty C10; public RectReactiveProperty C11; public AnimationCurveReactiveProperty C12; public BoundsReactiveProperty C13; public QuaternionReactiveProperty C14; } }
想使用以上类型以外的情况,需要自己对其定义
-
使用ReactiveProperty 的自定义类,在编辑器上设定
using System; using UniRx; namespace Sample.Section3.ReactiveProperty { // Fruit Enum public enum Fruit { Apple, Banana, Peach, Melon, Orange } // Fruit 型的 ReactiveProperty [Serializable] public class FruitReactiveProperty : ReactiveProperty<Fruit> { public FruitReactiveProperty() { } public FruitReactiveProperty(Fruit init) : base(init) { } } }
但是这样并不会在编辑器上显示,需要进行编辑器扩张
using UniRx; namespace Sample.Section3.ReactiveProperty.Editor { // 编辑器扩张 [UnityEditor.CustomPropertyDrawer(typeof(FruitReactiveProperty))] public class ExtendInspectorDisplayDrawer : InspectorDisplayDrawer { } }
这样就可以在编辑器上 定义了
3.2.2 ReadOnlyReactiveProperty
读取专用的ReactiveProperty,不能写
-
使用例
using UniRx; using UnityEngine; namespace Sample.Section3.ReactiveProperty { public class ReadOnlyReactivePropertySample : MonoBehaviour { private void Start() { //Int型的 ReactiveProperty var intReactiveProperty = new ReactiveProperty<int>(100); // int型的 ReadOnlyReactiveProperty var readOnlyInt = // ReactiveProperty 变换成 ReadOnlyReactiveProperty intReactiveProperty.ToReadOnlyReactiveProperty(); // 可读 Debug.Log("现在的值:" + readOnlyInt.Value); //可以订阅 readOnlyInt.Subscribe(x => Debug.Log("通知的值 :" + x)); // 不可写 // readOnlyInt.Value = 10; intReactiveProperty.Dispose(); } } }
-
IReadOnlyReactiveProperty
IReadOnlyReactiveProperty这个接口定义了 ReadOnlyReactiveProperty 的行为
namespace UniRx { public interface IReadOnlyReactiveProperty<T> : IObservable<T> { T Value { get; } bool HasValue { get; } } }
ReactiveProperty 继承了 IReadOnlyReactiveProperty ,所有 ReactiveProperty 可以 转换成 ReadOnlyReactiveProperty
using System.Collections;
using UniRx;
using UnityEngine;
namespace Sample.Section3.ReactiveProperty
{
//倒计时
public class ReactivePropertyTimerSample : MonoBehaviour
{
// 定义 ReactiveProperty
[SerializeField]
private IntReactiveProperty _current = new IntReactiveProperty(60);
// 现在的倒计时的时间 (读取专用)
// ReactiveProperty 转换成 IReadOnlyReactiveProperty
public IReadOnlyReactiveProperty<int> CurrentTime => _current;
//
private void Start()
{
StartCoroutine(CountDownCoroutine());
_current
.Subscribe(_x =>
{
Debug.Log($"倒计时 {_x}");
}).AddTo(this);
}
private IEnumerator CountDownCoroutine()
{
while (_current.Value > 0)
{
// 1秒 更新 1此
_current.Value--;
yield return new WaitForSeconds(1);
}
}
}
}
3.2.3 ReactiveCollection
ReactiveCollection 对 List 最佳发行消息功能。
• ObserveAdd :要素添加
• ObserveRemove :要素删除
• ObserveReplace : 要素变更
• ObserveCountChanged:要素总数变更
• ObserveMove :要素索引变更
• ObserveReset :List Clear
使用例
using UniRx;
using UnityEngine;
namespace Sample.Section3.ReactiveProperty
{
public class ReactiveCollectionSample : MonoBehaviour
{
private void Start()
{
var rc = new ReactiveCollection<int>();
//订阅 要素增加的消息
rc.ObserveAdd()
.Subscribe((CollectionAddEvent<int> a) =>
{
Debug.Log($"Add [{a.Index}]:{a.Value}");
});
//订阅 要素删除的消息
rc.ObserveRemove()
.Subscribe((CollectionRemoveEvent<int> r) =>
{
Debug.Log($"Remove [{r.Index}]:{r.Value}");
});
// 订阅 要素更新 的消息
rc.ObserveReplace()
.Subscribe((CollectionReplaceEvent<int> r) =>
{
Debug.Log($"Replace [{r.Index}]:{r.OldValue} -> {r.NewValue}");
});
// 订阅 要素个数更新 的消息
rc.ObserveCountChanged()
.Subscribe((int c) =>
{
Debug.Log($"Count: {c}");
});
// 订阅 要素的Index 变更的消息
rc.ObserveMove()
.Subscribe((CollectionMoveEvent<int> x) =>
{
Debug.Log($"Move {x.Value}:[{x.OldIndex}] -> [{x.NewIndex}]");
});
rc.Add(1);
rc.Add(2);
rc.Add(3);
rc[1] = 5;
rc.RemoveAt(0);
// Dispose() 时候向 Observable 发送 OnCompleted的消息
rc.Dispose();
}
}
}
3.2.4 ReactiveDictionary<TKey, TValue>
ReactiveDictionary<TKey, TValue> 对 Dictionary<TKey, TValue> 增加 消息发送机能
• ObserveAdd :添加新的Key
• ObserveRemove :删除新的Key
• ObserveReplace :key的值变更
• ObserveCountChanged:要素总数的变更
• ObserveReset :Dictionary Clear()
using System;
using UniRx;
using Unity.VisualScripting;
using UnityEngine;
namespace Sample.Section3.ReactiveProperty
{
public class ReactiveDictionarySample : MonoBehaviour
{
private void Start()
{
var rd = new ReactiveDictionary<string, string>();
// 订阅 要素添加的消息
rd.ObserveAdd()
.Subscribe((DictionaryAddEvent<string, string> a) =>
{
Debug.Log($"[{a.Key}]里添加{a.Value}");
});
// 订阅 要素消除的消息
rd.ObserveRemove()
.Subscribe((DictionaryRemoveEvent<string, string> r) =>
{
Debug.Log($"[{r.Key}]里消除{r.Value}");
});
// 订阅 要素更新的消息
rd.ObserveReplace()
.Subscribe((DictionaryReplaceEvent<string, string> r) =>
{
Debug.Log($"[{r.Key}]的{r.OldValue}更新成{r.NewValue}");
});
// 订阅 要素总数更新的消息
rd.ObserveCountChanged()
.Subscribe((int c) =>
{
Debug.Log("要素总数" + c);
});
// Add
rd["Apple"] = "苹果";
rd["Banana"] = "香蕉";
rd["Lemon"] = "柠檬";
// Replace
rd["Apple"] = "红苹果";
// Remove
rd.Remove("Banana");
// Dispose() 时候向 Observable 发送 OnCompleted的消息
rd.Dispose();
}
}
}