CleanArchitectureを元に考えたUnityのクラス設計③ - ロジックのつなぎ込み

概要

前回の記事ではロジックについての設計を説明しました
今回の記事ではロジックのつなぎ込みを説明していきます

クラス図


Context

ContextはUseCaseを束ねる長のような存在でタイトル・ホーム・クエストな
どUnityのシーンレベルごとに存在します

Contextで使用するUseCase達を束ねて初期化や更新の呼び出しを行います
さらに別Contextへの遷移も集約しています

ClockContextを例にすると以下の機能を持ちます
・ClockUseCaseの初期化
・共通でもつFooterUseCaseの設定(シーンを切り替えるフッターボタンのUseCase)
 ・UseCaseの更新
・別のコンテキストへの遷移処理

public class ClockContext : Context
{
    [SerializeField]
    ClockView _clockView;

    int _clockUseCaseIndex;

    // アプリ開始時にいちどだけ呼ばれる関数
    public override void RunOnAwake()
    {
        _clockView.InitializeView();
    }
    
    // コンテキストロード時に呼ばれる
    protected override IEnumerator DoLoad(ContextContainer container)
    {
        // ClockUseCaseの生成
        _clockUseCaseIndex = CommonUseCaseType.MAX;
        var clockUseCase = new ClockUseCase(new ClockContainer(new ClockPresenter(_clockView), new TimeZoneGateway()));
        UseCases.Add(_clockUseCaseIndex, clockUseCase);

        // コンテキストごとに共有でもつUseCaseもある
        (UseCases[CommonUseCaseType.FOOTER] as FooterUseCase)?.SetupByContext(OnChangeStopwatch);
    }

    // マイフレーム更新
    protected override void OnUpdate(float dt)
    {
        foreach (var useCase in UseCases)
        {
            useCase.Value.OnUpdate(dt);
        }
    }
    
    // 別のコンテキストへ遷移
    void OnChangeStopwatch()
    {
        ChangeContext(Contexts["StopwatchContext"], new StopwatchContextContainer());
    }
}

Container

Containerは引数をまとめたものでUseCaseやContextが保持することでInterfaceを変えずに引数へのアクセスを容易にするのが目的です

代わりにDIを使用することもできますが、ルールをしっかりしないとグローバル変数のような誰でもアクセスできてしまう状況が発生し、データがなぜ更新されているのかわからなくなりカオスが起きることがあります。

それが制御できるのであればZenject / VContainerなどを使用するのも良いでしょう

public class ClockContainer
{
    public IClockPresenter<IClockView> Presenter { get; }
    public ITimeZoneGateway TimeZoneGateway { get; }
    
    public ClockContainer(IClockPresenter<IClockView> presenter, ITimeZoneGateway timeZoneGateway)
    {
        Presenter = presenter;
        TimeZoneGateway = timeZoneGateway;
    }
}

シーンでの持ち方

まとめ

実際にはSceneManagerやフェードの処理もあるのでもう少し複雑にはなりますが、ContextとContainerの役割はとてもシンプルなのでわかりやすいと思います
Contextを介すことでシーンの切り替えや切り替え時の初期化処理の管理を明瞭かして、バグを防ぐことができます

コードに出てくる継承しているContextやGatewayとは?

説明のためにコードを簡略しており、ContextやTimeZoneGatewayに関しての詳細は省いているのですが、次のページで全コードを公開しているので記事を読み進めていただければ詳細がわかります。。。!(有料)

次回予告:データの管理方法

ロジックとそのロジックをつなげる方法をここまで書いてきました
次の記事からはいわゆるマスターデータやプレイヤーデータを読み書きする仕組みについて書いていこうと思います

https://note.com/r_kajiya/n/ne9b653d1e805


この記事が気に入ったらサポートをしてみませんか?