コガネブログ

平日更新を目標に Unity や C#、Visual Studio、ReSharper などのゲーム開発アレコレを書いていきます

【Unity】Redux のように状態管理できる「Unidux」紹介

はじめに

「Unidux」を Unity プロジェクトに導入することで
Redux のように状態管理できるようになります

導入方法

https://github.com/mattak/Unidux/releases

上記のページから .unitypackage をダウンロードして
Unity プロジェクトにインポートします

使用例

1.状態管理するシングルトンなコンポーネントを作成してシーンに配置します

using Unidux;
using UniRx;

public sealed class Example
    : SingletonMonoBehaviour<Example>, IStoreAccessor
{
    private Store<State> m_store;

    public IStoreObject StoreObject { get { return Store; } }

    public static State State { get { return Store.State; } }

    public static Subject<State> Subject { get { return Store.Subject; } }

    public static Store<State> Store
    {
        get
        { 
            return Instance.m_store = 
                Instance.m_store ?? 
                new Store<State>( new State(), new Count.Reducer() )
            ; 
        }
    }

    public static object Dispatch<TAction>( TAction action )
    {
        return Store.Dispatch( action );
    }

    private void Update()
    {
        Store.Update();
    }
}

2.ゲームの状態を格納するクラスを作成します

using System;
using Unidux;

[Serializable]
public sealed class State : StateBase
{
    public int Count;
}

3.状態を変更するアクションを定義します

using Unidux;

public static class Count
{
    public enum ActionType
    {
        Increment,
        Decrement
    }

    public sealed class Action
    {
        public ActionType ActionType;

        public Action( ActionType actionType )
        {
            ActionType = actionType;
        }
    }

    public static class ActionCreator
    {
        public static Action Create( ActionType type )
        {
            return new Action( type );
        }

        public static Action Increment()
        {
            return new Action( ActionType.Increment );
        }

        public static Action Decrement()
        {
            return new Action( ActionType.Decrement );
        }
    }

    public sealed class Reducer : ReducerBase<State, Action>
    {
        public override State Reduce( State state, Action action )
        {
            switch ( action.ActionType )
            {
                case ActionType.Increment:
                    state.Count++;
                    break;
                case ActionType.Decrement:
                    state.Count--;
                    break;
            }

            return state;
        }
    }
}

4.描画クラスを作成して Text オブジェクトにアタッチします

using UniRx;
using UnityEngine;
using UnityEngine.UI;

[RequireComponent( typeof( Text ) )]
public sealed class CountRenderer : MonoBehaviour
{
    private void OnEnable()
    {
        var text = GetComponent<Text>();

        Example.Subject
            .TakeUntilDisable( this )
            .StartWith( Example.State )
            .Subscribe( state => text.text = state.Count.ToString() )
            .AddTo( this )
        ;
    }
}

5.状態を変更するクラスを作成した Button オブジェクトにアタッチします

using UniRx;
using UnityEngine;
using UnityEngine.UI;

[RequireComponent( typeof( Button ) )]
public sealed class CountDispatcher : MonoBehaviour
{
    private void Start()
    {
        GetComponent<Button>()
            .OnClickAsObservable()
            .Subscribe( state => Example.Store.Dispatch( Count.ActionCreator.Increment() ) )
            .AddTo( this )
        ;
    }
}

このようなコードを作成することで使用できます

関連記事