Pull to refresh

Comments 16

А почему нельзя использовать обычный rx? (не знаток юнити)

В unirx много расширений для удобства работы с классами unity.

Я немного выпал из Unity разработки, но ведь UniRx больше не поддерживается и даже не работает в Unity 2022, разве нет?

Проверил на 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.

Когда руки дойдут посмотрю ещё раз

It's really handy and nice react for unity, but there some issue with recent version. I found that something like OnMouseDownAsObservable function doesn't work with Unity's new input system. Есть такой комментарий.

Небольшая подсказка. Вместо

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 опечатка, -= вместо +=

Sign up to leave a comment.

Articles