LoginSignup
4
4

More than 3 years have passed since last update.

【Unity】UniRxでシーン遷移を管理する

Last updated at Posted at 2019-06-30

はじめに

何らかのトリガーによりシーンを遷移する処理をUniRxを用いて実装する方法を書きました。

実行環境

  • Unity 2019 1.6f1 (c) Unity Technologies ApS.

  • UniRx 6.2.2 The MIT License (MIT) Copyright (c) 2018 Yoshifumi Kawai.

  • Zenject 7.3.1 Copyright (c) 2010-2019 Modest Tree Media Inc.

方法

主なクラスはSceneEntityChangeSceneUseCaseの2つです。

SceneEntity

SceneEntityの役割はシーンのデータの管理とそのデータの更新です。

SceneEntityはデータをReactivePropertyとして持ち、またこのデータを更新するためのメソッドを持ちます。

ChangeSceneUseCase

ChangeSceneUseCaseSceneEntityが持っているReactivePropertyを購読し、シーン遷移の具体的な処理を行います。

コード

SceneEntity

using UnityEngine;
using UniRx;

namespace Domain.Entity
{
    public class SceneEntity : ISceneEntity
    {
        public IReactiveProperty<Scene> SceneRP { get; }

        public SceneEntity()
        {
            SceneRP = new ReactiveProperty<Scene>(Scene.TitleScene);
        }

        public void ChangeScene(Scene targetScene)
        {
            SceneRP.Value = targetScene;
        }
    }

    public enum Scene
    {
        TitleScene,
        GameScene
    }

    public interface ISceneEntity
    {
        IReactiveProperty<Scene> SceneRP { get; }
        void ChangeScene(Scene targetScene);
    }
}

ChangeSceneUseCase


using UnityEngine;
using Zenject;
using Domain.Entity;
using UniRx;
using UnityEngine.SceneManagement;

namespace Domain.UseCase
{
    public class ChangeSceneUseCase : IInitializable, IChangeSceneUseCase
    {
        [Inject] private ISceneEntity sceneEntity;

        void IInitializable.Initialize()
        {
            sceneEntity
                .SceneRP
                .SkipLatestValueOnSubscribe() //初期値のプッシュを無視する
                .Subscribe(scene => LoadScene(scene.ToString()));
        }

        public void LoadScene(string sceneName)
        {
            SceneManager.LoadScene(sceneName);
        }
    }

    public interface IChangeSceneUseCase
    {

    }
}

説明

SceneEntity

シーンのデータを管理するためにIReactivePropety<Scene>型のSceneRPを宣言しています。

public IReactiveProperty<Scene> SceneRP { get; }

Sceneというのはこのような列挙型です。

public enum Scene
{
     TitleScene,
     GameScene
}

この例ではTitleSceneとGameSceneのみですが、他のシーンを追加したりする場合はここに新たな変数を追加します。

また、SceneEntitySceneRPを更新するためにChangeSceneというメソッドを持ちます。

public void ChangeScene(Scene targetScene)
{
     SceneRP.Value = targetScene;
}

遷移先のシーンを引数で指定してSceneRPを更新します

SceneEntityは次のようなインターフェースを実装し、ChangeSceneUseCassesceneEntityという変数にInjectします。

public interface ISceneEntity
{
     IReactiveProperty<Scene> SceneRP { get; }
     void ChangeScene(Scene targetScene);
}

ChangeSceneUseCase

ZenjectのIInitializableを実装しているので、開始時にInitializeメソッドが実行されます。

このInitializeメソッド内でsceneEntity.SceneRPSubscribeして、
新しいシーンへ遷移する処理を登録します。

使い方

うっかり忘れてしまいがちですが、ZenjectのInstaller内でそれぞれのクラスを忘れずにBindします。

Container.Bind<ISceneEntity>().To<SceneEntity>().AsCached();

Container.BindInterfacesTo<ChangeSceneUseCase>().AsCached();

そして、他のクラスで

[Inject] ISceneEntity sceneEntity;

SceneEntityを取得し、遷移したいタイミングで

sceneEntity.ChangeScene(Scene.GameScene);

などとすればシーン遷移できるはずです。

備考

今回はSceneEntityChangeSceneUseCaseという2つのクラスをわざわざ作って関心の分離を試みましたが、そこまで拘らない場合は1つのクラスにまとめてしまっても良いと思います。

4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4