1. 程式人生 > >遊戲開發中的設計模式——狀態模式

遊戲開發中的設計模式——狀態模式

Siki學院——遊戲開發中的設計模式

狀態模式—— 菜鳥篇個人學習筆記

案例開發——應用於場景轉換

由StartState場景,自動跳轉到MainMenuState場景,點選按鈕後,跳轉到BattleState場景

 GameLoop

採用了指令碼和遊戲物體分離的開發模式

using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.EventSystems;

public class GameLoop : MonoBehaviour {

    private SceneStateControl controller = null;

    void Awake() {
        DontDestroyOnLoad(this.gameObject);
    }


	void Start () {
        controller = new SceneStateControl();
        controller.SetState(new StartState(controller),false);//設定預設狀態 為開始狀態,不需要載入場景
	}
	

	void Update () {
        controller.StateUpdate();
	}
}

SceneStateControl

using System;
using System.Collections.Generic;
using System.Text;
using UnityEngine;
using UnityEngine.SceneManagement;

public class SceneStateControl
{
    private ISceneState mState;
    private AsyncOperation mAO;
    private bool mIsRunStart = false;
    /// <summary>
    /// 設定狀態(場景)
    /// </summary>
    /// <param name="state"></要設定的狀態,即卻換到那個狀態>
    /// <param name="isLoadScene"></增加判斷是否需要載入場景>
    public void SetState(ISceneState state,bool isLoadScene=true) //增加判斷是否需要載入場景
    { 
        if(mState!=null)
        {
            mState.StateEnd();//讓上一個場景做一下清理工作    
        }
        mState = state;      //設定新狀態
        if(isLoadScene)
        {
            mAO = SceneManager.LoadSceneAsync(mState.SceneName);//非同步載入,返回一個AsyncOperation
            //mState.StateStart();//若LoadScene直接寫在這裡,可能出現場景還沒載入完成,就執行了例如夾雜元件之類的操作,會出現問題
            mIsRunStart = false;
        }
        else
        {
            mState.StateStart();    //執行進入狀態方法
            mIsRunStart = true ;
        }
       
    }

    public void StateUpdate() {
        if (mAO != null && mAO.isDone == false) return;

        if (mIsRunStart==false&& mAO != null && mAO.isDone == true)
        {
            mState.StateStart();    //執行進入狀態方法
            mIsRunStart = true;
        }
        if (mState!=null)
        {
            mState.StateUpdate();
        }
    }
}

 ISceneState

using System;
using System.Collections.Generic;
using System.Text;
using UnityEngine;

public  class ISceneState
{
    private string mSceneName;
    protected SceneStateControl mControler;

    public ISceneState(string  sceneName, SceneStateControl controller) {
        mSceneName = sceneName;
        mControler = controller;
    }

    public string SceneName {
        get { return mSceneName; }
    }

    public virtual void StateStart() { }//進入狀態時--例:得到場景中的元件
    public virtual void StateEnd() { }//離開狀態時--例:銷燬遊戲物體
    public virtual void StateUpdate() { }//狀態中的操作
}

具體狀態(StartState、MainState、AttackState) 

StartState

using UnityEngine.UI;
using UnityEngine;

public  class StartState:ISceneState
{
    public StartState(SceneStateControl controller): base("01StartScene",controller)
    { 
        
    }

    private Image mLogo;
    private int mSmothTime=1;
    private float mWaitTime = 2;

    public override void StateStart()
    {
        mLogo = GameObject.Find("BG").GetComponent<Image>();
        mLogo.color = Color.black;
    }

    public override void StateUpdate()
    {
        mLogo.color = Color.Lerp(mLogo.color,Color.white,mSmothTime*Time.deltaTime);
        mWaitTime -= Time.deltaTime;
        if (mWaitTime<=0)
        {
            mControler.SetState(new MainState(mControler));
        }

    }
}

MainState

using System;
using System.Collections.Generic;
using System.Text;
using UnityEngine;
using UnityEngine.UI;


public  class MainState:ISceneState
{
    public MainState(SceneStateControl controller): base("02MainScene", controller)
    { 
        
    }

    public override void StateStart()
    {
        GameObject.Find("StartButton").GetComponent<Button>().onClick.AddListener(OnStartBtnClick);
    }

    private void OnStartBtnClick() 
    {
        mControler.SetState(new AttackState(mControler));
    }
}

 AttackState

 

using System;
using System.Collections.Generic;
using System.Text;

public  class AttackState:ISceneState
{
    public AttackState(SceneStateControl controller): base("03AttackScene", controller)
    { 
        
    }
}