인 게임 흐름 객체화하기

2019. 7. 27. 18:56인 게임 상태 전환 구현

InGameState 클래스 구현

InGameState 클래스는 게임의 흐름 객체인 초기화, 이동, 전투, 결과를 객체화하기 위한 추상 클래스입니다. 흐름 객체는 진행하면서 Start, Update, End의 상태 전환을 거치므로 FSM을 상속을 받습니다.

public abstract class InGameState : NFSM
{
    public virtual void Initailize(InGameView inGameView)
    {
        mInGameView = inGameView;
    }
 
    public virtual void Initailize(InGamePlay inGamePlay)
    {
        mInGamePlay = inGamePlay;
    }
 
    public InGameView GetView()
    {
        return mInGameView;
    }
 
    public InGamePlay GetPlay()
    {
        return mInGamePlay;
    }
 
    protected InGameView mInGameView;
    protected InGamePlay mInGamePlay;
}

함수

Initailize(InGameView inGameView)

상태 객체를 초기화하는 함수입니다. 매개인자의 InGameView의 경우 다음 상태를 전환하거나 해당 자원을 참조하기 위함입니다.

Initailize(InGamePlay inGamePlay)

상태 객체를 초기화하는 함수입니다. 매개인자의 InGamePlay의 경우 다음 상태를 전환하거나 해당 자원을 참조하기 위함입니다.

GetView()

InGameView를 리턴하는 함수입니다.

GetPlay()

InGamePlay를 리턴하는 함수입니다.

변수

mInGameView

매개인자로부터 받은 InGameView를 저장하는 변수입니다

mInGamePlay

매개인자로부터 받은 InGamePlay를 저장하는 변수입니다.

InGameEntry

InGameEntry는 초기화 흐름을 구현하는 흐름 객체입니다. 한 번 초기화하고 난 뒤 다시 플레이를 하지 않는 이상 호출되지 않습니다.

public abstract class InGameEntry : InGameState
{
    public override void Initailize(InGameView inGameView)
    {
        //Do It...
        base.Initailize(inGameView);
    }
 
    protected override void _Start()
    {
        //Do It...
        base._Start();
    }
 
    protected override void _Update()
    {
        //Do It...
        base._Update();
    }
 
    protected override void _End()
    {
        //Do It...
        base._End();
    }
}

초기화를 인 게임별로 따로 처리할 필요가 있을 수도 있으므로 상속을 받아서 별도로 처리합니다.

InGameEntrySingle의 경우 스토리 모드와 같이 단일 모드에서 초기화를 할 때 사용되는 클래스입니다.

public class InGameEntrySingle : InGameEntry
{
    public override void Initailize(InGameView inGameView)
    {
        //Do It...
        base.Initailize(inGameView);
    }
 
    protected override void _Start()
    {
        base._Start();
 
        Debug.Log("_Start InGameEntrySingle");
    }
 
    protected override void _Update()
    {
        base._Update();
 
        Debug.Log("_Update InGameEntrySingle");
    }
 
    protected override void _End()
    {
        base._End();
 
        Debug.Log("_End InGameEntrySingle");
 
        mInGameView.NextState(InGameView.eState.Play);
    }
}

InGameEntryPvPe의 경우 PvP 모드와 같이 대전 모드에서 초기화를 할 때 사용되는 클래스입니다.

public class InGameEntryPvP : InGameEntry
{
    public override void Initailize(InGameView inGameView)
    {
        //Do It...
        base.Initailize(inGameView);
    }
 
    protected override void _Start()
    {
        base._Start();
 
        Debug.Log("_Start InGameEntryPvP");
    }
 
    protected override void _Update()
    {
        base._Update();
 
        Debug.Log("_Update InGameEntryPvP");
    }
 
    protected override void _End()
    {
        base._End();
 
        Debug.Log("_End InGameEntryPvP");
 
        mInGameView.NextState(InGameView.eState.Play);
    }
}

InGameMove, InGameBattle, InGameResult

InGameEntry와 같은 방식으로 구현을 하면서 필요에 따라서 별도로 처리가 필요하면 클래스를 상속받아서 구현하시면 됩니다.

InGamePlay

흐름의 안에서 흐름을 분리하여 관리하는 부분이 필요한 경우가 발생할 수도 있습니다. 예를 들면 InGameMove 와 InGameBattle는 캐릭터가 생성이 완료되었고 진행하는 부분인데 진행하는 중에만 별도로 처리를 하고 싶다와 같은 경우가 있습니다. 이런 경우 다음과 같은 구현 방법이 있습니다.

public class InGamePlay : InGameState
{
    public override void Initailize(InGameView inGameView)
    {
        base.Initailize(inGameView);
 
        mStates = GetFSMList();
 
        for (int i = 0; i < mStates.Count; ++i)
        {
            mStates[i].Initailize(this);
        }
    }
 
    protected override void _Start()
    {
        State = eState.Update;
 
        StartState(ePlayState.Move);
    }
 
    protected override void _Update()
    {
        if (!IsPause())
        {
            mCurrentState.Update();
        }
    }
 
    protected override void _End()
    {
        base._End();
 
        mCurrentState = null;
 
#if UNITY_EDITOR
        Debug.Log("Play State 끝");
#endif
        mInGameView.NextState(InGameView.eState.Result);
    }
 
    public void StartState(ePlayState state)
    {
        if (mStates != null)
        {
            int next = (int)state;
 
            if (next < mStates.Count)
            {
                PlayState = state;
 
                mCurrentState = mStates[(int)state];
                mCurrentState.Start();
            }
        }
    }
 
    public void NextState(ePlayState next)
    {
        if (next == ePlayState.Result)
        {
            State = eState.End;
        }
        else
        {
            StartState(next);
        }
    }
 
    private List<InGameState> GetFSMList()
    {
        List<InGameState> fsmList = null;
 
        fsmList = new List<InGameState>
        {
            //인덱스 순서는 eGame 참고 
            new InGamePlayMoveSingle(),
            new InGamePlayBattle()
        };
 
        //switch (PlayData.Instance.PlayMode)
        //{
        //    case PlayData.ePlayMode.Single:
        //        fsmList = new List<InGameState>
        //        {
        //            new InGamePlayMoveSingle(),
        //            new InGamePlayBattle()
        //        };
        //        break;
 
        //    case PlayData.ePlayMode.PvP:
        //    case PlayData.ePlayMode.PTvPT:
        //        fsmList = new List<InGameState>
        //        {
        //            new InGamePlayMovePvP(),
        //            new InGamePlayBattlePvP()
        //        };
        //        break;
        //}
 
        return fsmList;
    }
 
    private List<InGameState> mStates;
 
    private InGameState mCurrentState;
 
    private ePlayState PlayState = ePlayState.None;
 
    public enum ePlayState : byte
    {
        Move,
        Battle,
        Result,
        None = 127,
    }
}

InGameView와 마찬가지로 구현 방식은 동일합니다.

'인 게임 상태 전환 구현 ' 카테고리의 다른 글

클래스 구조  (0) 2019.07.27
FSM 구현하기  (0) 2019.07.27
InGameView 구현하기  (0) 2019.07.27
개요  (0) 2019.07.27