設計模式篇:狀態模式(二)
阿新 • • 發佈:2018-11-26
完整工程:https://gitee.com/NKG/DesignPatterns/blob/master/DesignPatterns.unitypackage
首先在Unity下面建立如下檔案
首先是場景都要繼承的
ISceneState
其中包括了場景的生命週期函式,場景名稱,場景控制器的引用。
using System.Collections; using System.Collections.Generic; using Scenes.Scripts.StatePattern.RealSample; using UnityEngine; public class ISceneState { private string m_StateName = "ISceneState"; public string StateName { get { return m_StateName; } set { m_StateName = value; } } protected SceneStateController m_Controller = null; public ISceneState(SceneStateController Controller) { m_Controller = Controller; } /// <summary> /// 進入場景時呼叫的函式 /// </summary> public virtual void StateBegin() { } /// <summary> /// 場景結束時呼叫的函式 /// </summary> public virtual void StateEnd() { } /// <summary> /// 場景更新 /// </summary> public virtual void StateUpdate() { } }
場景控制器
using UnityEngine; using UnityEngine.SceneManagement; public class SceneStateController { private ISceneState m_State; private bool m_bRunBegin = false; private AsyncOperation _asyncOperation; public SceneStateController(){} public void SetState(ISceneState state, string LoadSceneName) { m_bRunBegin = false; LoadScene(LoadSceneName); if (m_State != null) { m_State.StateEnd(); } m_State = state; } private void LoadScene(string loadSceneName) { if (string.IsNullOrEmpty(loadSceneName)) { return; } _asyncOperation = SceneManager.LoadSceneAsync(loadSceneName); } public void StateUpdate() { //如果上一個場景還沒有載入完,那就讓他繼續載入 if (_asyncOperation!=null) { if(!_asyncOperation.isDone) return; } if (m_State != null && m_bRunBegin == false) { m_State.StateBegin(); m_bRunBegin = true; } if (m_State != null) { m_State.StateUpdate(); } } }
遊戲入口
using System; using System.Collections; using System.Collections.Generic; using Scenes.Scripts.StatePattern.RealSample; using UnityEngine; public class GameEntry : MonoBehaviour { SceneStateController m_SceneStateController=new SceneStateController(); private void Awake() { GameObject.DontDestroyOnLoad(this.gameObject); } // Use this for initialization private void Start () { //設定起始場景 m_SceneStateController.SetState(new StartState(m_SceneStateController),"StartState"); } // Update is called once per frame //更新狀態 void Update () { m_SceneStateController.StateUpdate(); } }
開始場景
using UnityEngine;
public class StartState : ISceneState
{
public StartState(SceneStateController Controller) : base(Controller)
{
this.StateName = "StartState";
}
public override void StateBegin()
{
Debug.Log("進入開始場景");
}
/// <summary>
/// 更換場景
/// </summary>
public override void StateUpdate()
{
//按下滑鼠左鍵來切換場景
if (Input.GetMouseButtonDown(0))
{
m_Controller.SetState(new MainMenuState(m_Controller), "MainMenuState");
}
}
}
選單場景中我們需要一個按鈕來進入戰鬥,開啟選單場景,新建Button
using UnityEngine;
using UnityEngine.UI;
public class MainMenuState : ISceneState
{
/// <summary>
/// 獲取改變場景按鈕的引用
/// </summary>
public Button ChangeState;
public MainMenuState(SceneStateController Controller) : base(Controller)
{
this.StateName = "MainMenuState";
}
public override void StateBegin()
{
ChangeState = GameObject.Find("Button").GetComponent<Button>();
ChangeState.onClick.AddListener(ToChangestate);
Debug.Log("進入選單場景");
}
private void ToChangestate()
{
Debug.Log("開始戰鬥的按鈕被點選,正在切換到戰鬥場景");
m_Controller.SetState(new BattleState(m_Controller), "BattleState");
}
}
戰鬥場景
using UnityEngine;
public class BattleState:ISceneState
{
public BattleState(SceneStateController Controller) : base(Controller)
{
this.StateName = "BattleState";
}
public override void StateBegin()
{
Debug.Log("進入戰鬥場景");
}
public override void StateEnd()
{
Debug.Log("戰鬥結束,回到選單場景");
}
public override void StateUpdate()
{
if (Input.GetMouseButtonDown(0))
{
m_Controller.SetState(new MainMenuState(m_Controller),"MainMenuState");
}
}
}
回到Unity,在GameEntry裡建立一個空的GameObject,將GameEntry指令碼掛載上去。
把這幾個場景Build
點選執行