Unity・3DCG技術ブログ

TAもどきによるUnity・3DCGに関する記事をアップします。

UniRx+Zenjectで作るシーン遷移基盤 メモその1

UnityでUniRxとZenjectを使ってのソシャゲを意識したシーン遷移基盤を趣味で作ってます。 f:id:serialtv:20190812194023g:plain

初めに

仕事ではUniRxは使っているのですが、Zenjectは仕事では使ったことがありません。 最近はやりのZenjectの練習もかねて、UniRxとZenjectを組み合わせればいいものができるのではないかという 実験的な試みとして、ゆるゆると作っていきたいと思います。

すでに作ったものの基本的な機能を挙げていくと...

シーン遷移基盤基本機能

  • シーンに引数付きで遷移または加算ロード
  • シーン履歴機能(前の画面に戻れる)
  • Androidのバックキーでも戻れる(EditorではEscキー)
  • 特定の画面にURLジャンプ
  • 遷移時にトランジション演出

と、このあたりをすでに実装してます。

シーンに引数付きで遷移または加算ロード

NavigationServiceNavigateAsyncメソッドを呼ぶと、内部でZenjectSceneLoaderLoadSceneし、 遷移先にSceneBaseコンポーネントがあることを想定してFindし、 SceneBaseコンポーネントのPrepareSceneAsyncなどのインターフェイスを呼びだす流れとなっています。

NavigationServiceクラス抜粋

public static class NavigationService
{
    static public IMessageBroker Broker { get; } = new MessageBroker();
    static public IAsyncMessageBroker AsyncBroker { get; } = new AsyncMessageBroker();
    static Stack<SceneParam> sceneStack = new Stack<SceneParam>();
    static bool isNavigating;
    static ZenjectSceneLoader loader =>
        ProjectContext.Instance.Container.Resolve<ZenjectSceneLoader>();

    /// <summary>
    /// シーンを加算ロードします。
    /// </summary>
    /// <param name="sceneName">読み込むシーン名</param>
    /// <param name="argument">読み込むシーンで必要となる場合はパラメータを与えます</param>
    /// <returns></returns>
    public static IObservable<Unit> NavigateAsync(string sceneName, object argument = null)
    {
        var sceneParam = new SceneParam(sceneName, argument, isStack: true, loadSceneMode: LoadSceneMode.Additive);
        return NavigateAsyncCore(sceneParam);
    }

    ~いろいろ省略してます~

    static IEnumerator CoNavigateAsync(IEnumerable<SceneParam> sceneParams)
    {
        ~略~

        yield return DispatchAsync<AsyncBeginLoadSceneEvent>(new AsyncBeginLoadSceneEvent());
        foreach (var sceneParam in sceneParams)
        {
            yield return LoadSceneAsync(sceneParam, false);
        }
        yield return DispatchAsync<AsyncAfterLoadSceneEvent>(new AsyncAfterLoadSceneEvent());

        foreach (var sceneParam in sceneParams)
        {
            if (sceneParam.SceneBase != null) yield return sceneParam.SceneBase.StartSceneAsync().ToYieldInstruction();
        }
}

SceneBaseクラス抜粋

public abstract class SceneBase : MonoBehaviour
{
    // これがシーン遷移時にセットされる引数を表す
    [InjectOptional(Id = "SceneBaseArgument")] public object Argument { get; protected set; }

    public virtual void ArgParseTo(SceneParam p) { }

    public bool IsLoaded { get; set; }

    public virtual IObservable<SceneBase> PrepareSceneAsync()
    {
        return Observable.Return(this);
    }

    public virtual IObservable<Unit> StartSceneAsync()
    {
        return Observable.Return(Unit.Default);
    }
}

権利表記

Unityちゃんの素材を使用しました。 © Unity Technologies Japan/UCL

最後に

と、今日はこのへんで... その2に続く...

追記

UniRx+Zenjectで作るシーン遷移基盤 メモその2ZenjectBindingとか - 技術ブログ を書きました。