UniRx를 사용한 순차적 비동기 처리 기능


사드바의 카드 공연 등 이벤트 대열이 게임에 활용될 기회가 워낙 많아 해봤다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UniRx;
using System;

/// <summary>
/// 順番に非同期処理を処理していくクラス
/// </summary>
public class ObservableQueueWorker : IDisposable{

    bool running = false;
    List<Func<IObservable<Unit>>> eventQueue = new List<Func<IObservable<Unit>>> ();
    bool isDisposed = false;

    /// <summary>
    /// 非同期処理を追加
    /// </summary>
    public void Enqueue(Func<IObservable<Unit>> asyncAction){
        eventQueue.Add (asyncAction);
        if (!running) {
            running = true;
            SubscribeNext ();
        }
    }

    /// <summary>
    /// 先頭に割り込み
    /// </summary>
    public void InsertFirst(Func<IObservable<Unit>> asyncAction){
        if (running) {
            eventQueue.Insert (0, asyncAction);
        }else
            Enqueue (asyncAction);
    }

    /// <summary>
    /// 現在進行しているイベントが終わったらDisposeする
    /// </summary>
    public void EndLoop(){
        Debug.Log ("End Loop");
        InsertFirst (()=>Observable.Start(Dispose));
    }

    // 次のObservableを発火させる
    void SubscribeNext(){
        if (eventQueue.Count == 0 || isDisposed){
            Debug.Log ("Stop Running");
            running = false;
            return;
        }

        var e = eventQueue [0];
        eventQueue.RemoveAt (0);

        e ()
            .Finally (() => SubscribeNext ())
            .Subscribe ();
    }

    public void Dispose(){
        isDisposed = true;
    }
}

호출 측면 예


        var eventQueueWorker = new ObservableQueueWorker ();
        for (int i = 0; i < 10; i++) {
            int index = i;
            eventQueueWorker.Enqueue (()=>{
                Debug.Log(index);
                return Observable.Timer(TimeSpan.FromSeconds(1)).AsUnitObservable();
            });
        }

        Observable.Timer(TimeSpan.FromSeconds(2))
            .Subscribe(x=>eventQueueWorker.InsertFirst(()=>{
                Debug.Log("割り込み2秒");
                return Observable.Timer(TimeSpan.FromSeconds(2)).AsUnitObservable();
            }));

        Observable.Timer(TimeSpan.FromSeconds(6))
            .Subscribe(x=>eventQueueWorker.EndLoop());

총결산


나중에 실제로 사용해서 원하는 기능이 있으면 추가됩니다.
개선할 점이 있다면 메시지를 남겨주세요.

좋은 웹페이지 즐겨찾기