Комментарии 16
А почему нельзя использовать обычный rx? (не знаток юнити)
Проверил на 22.2.7. При первом приближении проблем не вижу. Проверял таким образом.
public class ScoreView : MonoBehaviour
{
[SerializeField] private ScoreUpdatable _scoreUpdatable;
[SerializeField] private TMP_Text _scoreCount;
[SerializeField] private Button _button;
[SerializeField] private Image _buttonLisener;
private bool _imageState;
private void Start()
{
_scoreUpdatable.Score.Subscribe(v => _scoreCount.text = v.ToString());
_button.onClick.AsObservable().Subscribe(v =>
{
_imageState = !_imageState;
_buttonLisener.color = _imageState ? Color.red : Color.yellow;
});
}
}
public class ScoreUpdatable : MonoBehaviour
{
private ReactiveProperty<int> _score = new ReactiveProperty<int>();
public IReactiveProperty<int> Score => _score;
private IEnumerator Start()
{
while (enabled)
{
yield return new WaitForSeconds(1);
_score.Value++;
}
}
}
Я, помнится, скачал какую-то самую новую версию Unity, поставил netstandard2.1, установил UniRx и получил конфликт Assemblies.
Когда руки дойдут посмотрю ещё раз
Небольшая подсказка. Вместо
private List<IDisposable> _disposables = new List<IDisposable>();
можно использовать класс CompositeDisposable для простоты. Будет что-то типа
private CompositeDisposable _disposables = new CompositeDisposable();
public void Init(Player player)
{
player.Health
//создаем подписку
.Subscribe(v => { _healthView.text = v.ToString(); })
//добавляем подпику в список очищаемых обьектов
.AddTo(_disposables);
player.Mana.Subscribe(v => { _manaView.text = v.ToString(); }).AddTo(_disposables);
}
public void Dispose()
{
_disposables.Dispose();
}
Благодарю! Не зная про CompositeDisposable, в результате написал свой аналог с другим именем :)
Да, у нас тоже используется аналог. Но у CompositeDisposable есть серьезный минус: у него внутри есть bool _disposed, которая не позволяет переиспользовать список.
public void Dispose()
{
var currentDisposables = default(IDisposable[]);
lock (_gate)
{
if (!_disposed)
{
_disposed = true;
currentDisposables = _disposables.ToArray();
_disposables.Clear();
_count = 0;
}
}
if (currentDisposables != null)
{
foreach (var d in currentDisposables)
if (d != null)
d.Dispose();
}
}
Тогда как наш под капотом работает точно так же, как и в примере в посте, то есть при диспоузе он просто диспоузит все элементы, а потом чистится
У CompositeDisposable есть метод Clear, который как раз делает то, что вам надо - у всех IDisposable вызовет Dispose, затем почистит список, но при этом _disposed не выставит в true. Т.е. можете переиспользовать его сколько угодно раз.
Это правда. На главной странице библиотеки в гитхабе даже есть об этом пункт. Но я люблю пользоваться подсказками умного Райдера, когда реализую IDisposable, а он в таком случае вызовет именно этот метод у CompositeDisposable при заполении метода. И очень просто забыть, что это надо обязательно поменять
Я наверное не первый заметно, но автор не корректно отписался от событий
Хотелось бы узнать о преимуществах UniRx. Просто я всегда использовал ReactiveUI + CommunityToolkit.Mvvm
Как уже отмечали выше, дело в заточенности под юнити. Сами авторы библиотеки помечают это как "Unity-specific Extra Gems"
// Unity's singleton UiThread Queue Scheduler
Scheduler.MainThreadScheduler
ObserveOnMainThread()/SubscribeOnMainThread()
// Global StartCoroutine runner
MainThreadDispatcher.StartCoroutine(enumerator)
// convert Coroutine to IObservable
Observable.FromCoroutine((observer, token) => enumerator(observer, token));
// convert IObservable to Coroutine
yield return Observable.Range(1, 10).ToYieldInstruction(); // after Unity 5.3, before can use StartAsCoroutine()
// Lifetime hooks
Observable.EveryApplicationPause();
Observable.EveryApplicationFocus();
Observable.OnceApplicationQuit();
В примере с событиями в методе Dispose опечатка, -= вместо +=
Совсем чуть-чуть про UniRx для Unity