例えばタイトル画面からホーム画面に遷移するとして、基盤を使う側のコードはこんな感じとなります。
コード
using UnityEngine; using UnityEngine.UI; using UniRx; using Zenject; public class Title : SceneBase { [Inject(Id = "start")] Button startButton; [Inject] TransitionController transitionController; void Start() { // タッチでホーム画面へ startButton.OnClickAsObservable().Subscribe(_ => { transitionController.LoadScene("Home", TransitionController.LoadingMode.LongLoading); }).AddTo(this); } }
using UnityEngine; using UnityEngine.UI; using Zenject; using UniRx; public class Home : SceneBase { [Inject(Id = "quest")] Button questButton; [Inject] TransitionController transitionController; void Start() { // Something code here ... } }
[SerializeField]でオブジェクトを直接リンクして参照するかわりに
ZenjectのInject
アトリビュートでもってインスタンスを注入します。
ZenjectBinding
UIの参照がInjectされるためにZenjectBindingコンポーネントを使用します。
ZenjectBinding
というコンポーネントをidentifier
とともに貼り付けておきます。
ProjectContext
Resources以下にあるProjectContext.prefab
はZenjectの仕組みによってゲーム起動直後にシーンに読み込まれます。
そして、DontDestroyなのでシーン遷移しても消えないグローバルオブジェクトです。
この性質を利用して、ProjectContext直下にトランジション演出用のコンポーネントTransitionController
を置きました。
こんな具合でProjectContext
以下に置いたCanvas
にあります。
そしてTransitionControllerのインスタンスをProjectContext
のグローバルなInstallerに下記のような
コードでアタッチさせています。
コード
using UnityEngine; using Zenject; using UniRx; using System.Linq; /// <summary> /// ProjectContextにアタッチされるグローバルなInstaller. /// </summary> public class ApplicationInstaller : MonoInstaller { [SerializeField] TransitionController transitionController; public override void InstallBindings() { Container.Bind<TransitionController>().FromInstance(transitionController).AsSingle(); } }
あと色々省略してますがTransitionControllerのコードです。
public class TransitionController : MonoBehaviour { public enum LoadingMode { // ローディング画面を挟まない None, // 長めのローディングになりそうな場合 LongLoading, } [SerializeField] GameObject view = default; [SerializeField] GameObject block = default; [SerializeField] Material transitionMaterial = default; LoadingMode loadingMode = LoadingMode.None; public void LoadScene(string sceneName, LoadingMode mode = LoadingMode.None, object argument = null) { loadingMode = mode; NavigationService.NavigateSingleAsync(sceneName, argument) .Subscribe(_ => { }, e => Debug.LogException(e)); } public void LoadSceneAdditive(string sceneName, object argument = null, LoadingMode mode = LoadingMode.None) { loadingMode = mode; NavigationService.NavigateAsync(sceneName, argument) .Subscribe(_ => { }, e => Debug.LogException(e)); } void Awake() { GameObject.DontDestroyOnLoad(this.gameObject); NavigationService.AsyncBroker.Subscribe<AsyncBeginLoadSceneEvent>(_ => Observable.FromCoroutine(Show)).AddTo(this); NavigationService.AsyncBroker.Subscribe<AsyncAfterLoadSceneEvent>(_ => Observable.FromCoroutine(Hide)).AddTo(this); NavigationService.Broker.Receive<BackButtonEvent>().Subscribe(_ => OnBackEvent()).AddTo(this); NavigationService.Broker.Receive<TapBlockEvent>().Subscribe(_ => block.SetActive(true)).AddTo(this); NavigationService.Broker.Receive<TapUnblockEvent>().Subscribe(_ => block.SetActive(false)).AddTo(this); } ....~~いろいろ略~~ }
最後に
その3に続く...(予定)