在以往的菜鸟生涯里,只会用动画的有限状态机,并不懂神魔是状态模式。
其实他们的原理是有点相似的:
首先,有一个接口,定义了他们的行为,对于Ui来说就是界面的抽象,暂且称它为PanelBase,它定义了界面的,清理(即先清除之前是用过的状态)、进入、改变、退出、以及持续性操作。
每个界面panel的类会继承并且实现这几部分功能,同时进行一些自己的扩展,所有的对象由一个状态管理器来使用字典储存,每一个界面即一个状态,并且有枚举来对应,我们只要调用StateManager里面封装好了的方法,即能改变状态(上一个状态的退出以及当前状态的进入),Statemanager可写成一个单例,方便使用。同时它的Update会调用当前状态的子OnUpDate函数。以实现持续调用。
通常我的UImanager来封装一些对panel的隐藏和显示,等等工具方法。同时在他的start方法进行所有状态的注册。
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
public class TW_UIManager : MonoBehaviour
{
private static TW_UIManager instance;
public static TW_UIManager InStance
{
get
{
return instance;
}
}
/// <summary>
/// canvas画布
/// </summary>
private Transform canvas;
public Transform Canvas
{
get
{
return canvas;
}
set
{
canvas = value;
}
}
private void Awake()
{
instance = this;
Init();
}
public void Init()
{
canvas = TW_Tool.FindOBJ("Canvas").transform;
TW_StateManager.Instance.InitAllState();
TW_StateManager.Instance.ChangeState(TW_State.Start);
}
public GameObject ShowPanel(GameObject tmObj, string tmName)
{
if (tmObj == null)
{
GameObject go = TW_Tool.LoadAndSetUI(Canvas, tmName, UIAnchors.Border);
if (go != null)
return go;
}
else
{
tmObj.transform.localScale = Vector3.one;
return tmObj;
}
return null;
}
public void YinPanel(GameObject tmOBj)
{
tmOBj.transform.localScale = Vector3.zero;
}
public void LoadSenceTo(string scenceName)
{
SceneManager.LoadScene(scenceName);
}
}
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class TW_StateManager
{
private static readonly TW_StateManager instance = new TW_StateManager();
public static TW_StateManager Instance
{
get
{
return instance;
}
}
public Dictionary<TW_State, TW_PanelBase> StateDic = new Dictionary<TW_State, TW_PanelBase>();
/// <summary>
/// 当前初始状态
/// </summary>
private TW_State m_NowState = TW_State.Null;
public void InitAllState()
{
//注册所有状态
StateDic[TW_State.Start] = new TW_StartPanel();
StateDic[TW_State.Level] = new TW_LevelPanel();
StateDic[TW_State.Defeat] = new TW_DeftPanel();
StateDic[TW_State.Game] = new TW_GamePanel();
//初始化所有状态(清空)
StateDic[TW_State.Start].Clear();
StateDic[TW_State.Level].Clear();
StateDic[TW_State.Defeat].Clear();
StateDic[TW_State.Game].Clear();
}
/// <summary>
/// 状态持续操作
/// </summary>
public void Update()
{
if (StateDic.Count == 0 || StateDic.ContainsKey(m_NowState) == false) return;
StateDic[m_NowState].PanelUpdate();
}
/// <summary>
/// 状态改变
/// </summary>
/// <param name="_state"></param>
public void ChangeState(TW_State _state)
{
if (m_NowState == _state && m_NowState != TW_State.Null) return;
if (!StateDic.ContainsKey(_state)) return;
m_NowState = _state;
StateDic[_state].PanelEnter();
}
public void StateExit()
{
if (m_NowState != TW_State.Null) { StateDic[m_NowState].PanelExit(); }
}
}
using UnityEngine;
using System.Collections;
public interface TW_PanelBase {
/// <summary>
/// 清空所有的数据
/// </summary>
void Clear();
/// <summary>
/// panel的进入
/// </summary>
void PanelEnter();
/// <summary>
/// 所有的持续调用操作
/// </summary>
void PanelUpdate();
/// <summary>
/// panel退出
/// </summary>
void PanelExit();
}
public enum TW_State
{
Start,
People,
Level,
Pause,
Game,
Defeat,
Succee,
Null
}
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class TW_LevelPanel : TW_PanelBase {
/// <summary>
/// 选择关卡界面
/// </summary>
private GameObject levelPanel;
private Button returnMian;
private GameObject[] suos;
public void Init()
{
levelPanel = TW_UIManager.InStance.ShowPanel(levelPanel, "LevelPanel");
returnMian = TW_Tool.FindButtonOnObj("Return");
TW_Tool.AddButtonOnClickLitener(returnMian, OnClickReturn);
for (int i = 1; i < 11; i++)
{
suos[i] = TW_Tool.FindOBJ("suo" + i.ToString());
}
}
public void OnClickReturn()
{
TW_StateManager.Instance.ChangeState(TW_State.Start);
PanelExit();
}
public void Clear()
{
levelPanel = null;
}
public void PanelEnter()
{
Init();
}
public void PanelExit()
{
TW_UIManager.InStance.YinPanel(levelPanel);
}
public void PanelUpdate()
{
}
}