Несколько тяжелых методов подряд в UniRx

Делаю загрузку мира. Есть несколько тяжелых методов для каждой стадии загрузки. Пытаюсь сделать их последовательно в другом потоке, при этом после каждого переключая надпись в загрузочном экране. Но, пока что, сделал какой-то костыль, и, мне кажется, что оно задействует так не два, а больше потоков:

/// PLAYGROUND GENERATION
LoadScreenHandler.SetProgressText(LoadScreenHandler.LoadingProgressType.WorldGeneration);
disposable = Observable.WhenAll(Observable.Start(() =>
{
    Playground.Initialize_Stage0(CurrentWorldData.RegionsSizes, GridGenerator.GenType.Lake);
})).ObserveOnMainThread().Subscribe(result =>
{
    /// TERRAIN INIT
    LoadScreenHandler.SetProgressText(LoadScreenHandler.LoadingProgressType.TerrainInit);
    disposable = Observable.WhenAll(Observable.Start(() =>
    {
        Playground.Initialize_Stage1();
    })).ObserveOnMainThread().Subscribe(result =>
    {
        /// TEXTURING
        LoadScreenHandler.SetProgressText(LoadScreenHandler.LoadingProgressType.Texturing);
        disposable = Observable.WhenAll(Observable.Start(() =>
        {
            Playground.Initialize_Stage2();
        })).ObserveOnMainThread().Subscribe(result =>
        {
            /// VILLAGE GENERATION
            LoadScreenHandler.SetProgressText(LoadScreenHandler.LoadingProgressType.VillageInit);
            CharacterNew.InstData[] charactersData = null;
            disposable = Observable.WhenAll(Observable.Start(() =>
            {
                Playground.Initialize_Stage3();
                charactersData = CurrentLoadType != LoadType.FromLoadedSave ?
                    Playground.CharactersGenerate() : SavesHandler.CurrentSubsave.CharactersData;
            })).ObserveOnMainThread().Subscribe(result =>
            {
                /// GROUND RES GENERATION
                GroundRes.InstData[,] groundResData = null;
                LoadScreenHandler.SetProgressText(LoadScreenHandler.LoadingProgressType.GroundResGen);
                disposable = Observable.WhenAll(Observable.Start(() =>
                {
                    groundResData = CurrentLoadType != LoadType.FromLoadedSave ?
                        GridGenerator.GenerateGroundRes() : SavesHandler.CurrentSubsave.GroundResData;
                })).ObserveOnMainThread().Subscribe(result =>
                {
                    /// INSTANTIATING
                    LinksHandler.inst.camh.Teleport(Playground.VillageStartPos);
                    Playground.Mesh_Instantiate();
                    Playground.Water_Instantiate();
                    BarrierHandler.Initialize();
                    Playground.GroundRes_Instantiate(groundResData);
                    Playground.Village_Instantiate();
                    Playground.Characters_Instantiate(charactersData);
                });
            });
        });
    });
});

И вот ещё, чтобы, если загрузка прерывается посредине, то не сломать:

private void OnApplicationQuit()
{
    if (disposable != null && !_isPlaygroundGenerated)
    {
        disposable.Dispose();
        Debug.Log("<color=red>Threads terminated.</color>");
    }
}

Как правильно это написать, чтобы было нормально, по порядку?

ps: Хотелось бы чтобы оно выполнялось в одном не основном потоке, последовательно друг за другом, и в промежутках после выполнения каждой стадии, можно было выполнять что то в основном потоке (в данном случае смена надписи на лоадскрине, но есть и другие нужды)


Ответы (1 шт):

Автор решения: Kurwo Attano

Пока что придумал вот такое решение тестовое. Кажется мне что это все равно костыли какие-то, но работает как мне надо.

private void Test8()
{
    var heavyMethod1 = Observable.Start(() =>
    {
        var timeToSleep = 1000;
        var returnedValue = 10;
        Debug.Log(string.Format("<color=magenta>1 Thread = {0} UtcNow = {1}</color>", Thread.CurrentThread.ManagedThreadId, System.DateTime.UtcNow));
        Thread.Sleep(timeToSleep);
        return returnedValue;
    });

    var heavyMethod2 = Observable.Start(() =>
    {
        var timeToSleep = 2000;
        var returnedValue = 20;
        Debug.Log(string.Format("<color=magenta>2 Thread = {0} UtcNow = {1}</color>", Thread.CurrentThread.ManagedThreadId, System.DateTime.UtcNow));
        Thread.Sleep(timeToSleep);
        return returnedValue;
    });        

    Part0();

    void Part0()
    {
        var observale = Observable.Zip(heavyMethod1)
        .ObserveOnMainThread().Subscribe(result =>
        {
            Debug.Log("<color=magenta>Part0 complete</color>");
            Part1();
        });
    }
    

    void Part1()
    {
        var observale = Observable.Zip(heavyMethod2)
        .ObserveOnMainThread().Subscribe(result =>
        {
            Debug.Log("<color=magenta>Part1 complete</color>");
            Part2();
        });
    }

    void Part2()
    {
        var observale = Observable.Zip(heavyMethod1)
        .ObserveOnMainThread().Subscribe(result =>
        {
            Debug.Log("<color=magenta>Part2 complete</color>");
            OnComplete();
        });
    }

    void OnComplete()
    {
        Debug.Log("<color=magenta>All complete</color>");
    }
}
→ Ссылка