定义
状态模式简单定义就是类的行为是基于它的状态改变的。
例如在王者荣耀中裴擒虎拥有人形态和虎形态。当玩家决定转换形态时,裴擒虎会进入虎形态,这时候裴擒虎会以虎形态来表现其行为,包含移动攻击和技能,当玩家决定转换为人形时,裴擒虎就会复原到人形态。所以这种转换可以看作为裴擒虎的一种内部状态的转换。通过外形的变化导致角色表现出另外一种的行为模式,但是无论怎样转换,操作的角色还是裴擒虎。
组成部分
一般设计状态模式分为三个部分,Context, Start, ConcreteState
Context(状态拥有者)是一个具有“状态”属性的类,可以定制相关的接口,让外界能够得知状态的修改,通过操作让状态改变。有状态属性的类,例如:角色的攻击,施法等状态。
State(状态接口类)制定状态的接口,负责规范Context的下要的表现行为。
ConcreteState(具体状态类)1.继承自State。2.实现Context在状态下特有的行为。如:实现角色在前行的状态下行动变缓,模型半透明。
游戏场景切换的应用
设计的脚本:
1.ISceneState场景类的接口,定义场景的转换和执行时需要调用的方法。
2.StartState,MainState,BattleState 作为场景执行的操作类。
3.SceneContext 场景状态的拥有者,保持当前游戏场景状态。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ISceneState
{
private SceneContext sceneContext;
public ISceneState(SceneContext sceneContext)
{
this.sceneContext = sceneContext;
}
public virtual void SceneBegin()
{
//加载游戏资源
}
public virtual void SceneEnd()
{
//释放游戏资源
}
public virtual void SceneUpdate()
{
//场景更新逻辑
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class StartState : ISceneState
{
private SceneContext sceneContext;
public StartState(SceneContext sceneContext):base(sceneContext)
{
this.sceneContext = sceneContext;
}
public override void SceneBegin()
{
Debug.Log("加载StartState");
this.sceneContext.SetState(new MainState(sceneContext), "MainScene");
}
public override void SceneEnd()
{
Debug.Log("释放StartState");
}
public override void SceneUpdate()
{
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MainState : ISceneState
{
private SceneContext sceneContext;
public MainState(SceneContext sceneContext):base(sceneContext)
{
this.sceneContext = sceneContext;
}
public override void SceneBegin()
{
Debug.Log("加载MainState");
this.sceneContext.SetState(new BattleState(sceneContext), "BattleScene");
}
public override void SceneEnd()
{
Debug.Log("释放MainState");
}
public override void SceneUpdate()
{
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BattleState : ISceneState
{
private SceneContext sceneContext;
public BattleState(SceneContext sceneContext):base(sceneContext)
{
this.sceneContext = sceneContext;
}
public override void SceneBegin()
{
Debug.Log("加载BattleState");
}
public override void SceneEnd()
{
Debug.Log("释放BattleState");
}
public override void SceneUpdate()
{
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class SceneContext : MonoBehaviour
{
private ISceneState sceneState;
private bool isLoadBegin;
private AsyncOperation asyncOperation;
public void SetState(ISceneState sceneState, string loadSceneName)
{
if (this.sceneState != null)
{
this.sceneState.SceneEnd();
}
this.sceneState = sceneState;
isLoadBegin = false;
LoadScene(loadSceneName);
}
private void LoadScene(string loadName)
{
if (!(loadName == null || loadName.Length == 0))
{
asyncOperation = SceneManager.LoadSceneAsync(loadName);
}
}
public void Update()
{
if (this.sceneState == null || (asyncOperation != null && asyncOperation.isDone == false))
return;
if (isLoadBegin == false)
{
isLoadBegin = true;
this.sceneState.SceneBegin();
}
this.sceneState.SceneUpdate();
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class Main : MonoBehaviour
{
private SceneContext sceneContext;
private void Awake()
{
GameObject.DontDestroyOnLoad(this.gameObject);
}
private void Start()
{
sceneContext = new SceneContext();
sceneContext.SetState(new StartState(sceneContext), "");
}
private void Update()
{
sceneContext.Update();
}
}
执行结果
优缺点
在场景设计中,属于“产出较少的状态类,但是如果有大量状态的系统时,就会遇到产出过多状态类的情况,会伴随类爆炸的问题。但是相比于传统的switch在后续的维护来看,仍然有优势。
文章评论