はじめに
何らかのトリガーによりシーンを遷移する処理を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.
方法
主なクラスはSceneEntity
とChangeSceneUseCase
の2つです。
SceneEntity
SceneEntity
の役割はシーンのデータの管理とそのデータの更新です。
SceneEntity
はデータをReactivePropertyとして持ち、またこのデータを更新するためのメソッドを持ちます。
ChangeSceneUseCase
ChangeSceneUseCase
はSceneEntity
が持っている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のみですが、他のシーンを追加したりする場合はここに新たな変数を追加します。
また、SceneEntity
はSceneRP
を更新するためにChangeScene
というメソッドを持ちます。
public void ChangeScene(Scene targetScene)
{
SceneRP.Value = targetScene;
}
遷移先のシーンを引数で指定してSceneRP
を更新します
SceneEntity
は次のようなインターフェースを実装し、ChangeSceneUseCasse
のsceneEntity
という変数にInjectします。
public interface ISceneEntity
{
IReactiveProperty<Scene> SceneRP { get; }
void ChangeScene(Scene targetScene);
}
ChangeSceneUseCase
ZenjectのIInitializable
を実装しているので、開始時にInitialize
メソッドが実行されます。
このInitialize
メソッド内でsceneEntity.SceneRP
をSubscribe
して、
新しいシーンへ遷移する処理を登録します。
使い方
うっかり忘れてしまいがちですが、ZenjectのInstaller内でそれぞれのクラスを忘れずにBindします。
Container.Bind<ISceneEntity>().To<SceneEntity>().AsCached();
Container.BindInterfacesTo<ChangeSceneUseCase>().AsCached();
そして、他のクラスで
[Inject] ISceneEntity sceneEntity;
でSceneEntity
を取得し、遷移したいタイミングで
sceneEntity.ChangeScene(Scene.GameScene);
などとすればシーン遷移できるはずです。
備考
今回はSceneEntity
とChangeSceneUseCase
という2つのクラスをわざわざ作って関心の分離を試みましたが、そこまで拘らない場合は1つのクラスにまとめてしまっても良いと思います。