当我们用Unity进行场景切换时,可能会写下如下代码:
using UnityEngine;
using UnityEngine.SceneManagement;
public class ReverseVersion : MonoBehaviour
{
private string _state = "到早上了";
public void ChanageScene(string StateName)
{
_state = StateName;
switch (_state)
{
case "到早上了":
Debug.Log("早上起来第一句,就给自己打个气");
SceneManager.LoadScene(0);
break;
case "到中午了":
Debug.Log("我饿了,我困了");
SceneManager.LoadScene(1);
break;
case "到晚上了":
Debug.Log("我不行了");
SceneManager.LoadScene(2);
break;
default:
break;
}
}
}
这样一看,没啥问题,可是,当场景之间转换的条件复杂了,场景多了,那又会是怎样的一副光景呢?
这个类也会越来越庞大,每增加一个场景,就要多一个case,无论任何场景,都需要它来改变。
再或者需要改一下需求和转换条件,你要改动的代码又有多少呢?
责任太过重大,违背了我们的“单一职责原则”
那就可以请出我们的的“状态模式”来解决问题
关于状态模式
- 当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。
- 状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂的情况。把状态的判断逻辑转移到表示不同状态的一系列类中,可以把复杂的判断逻辑简化。对于Unity场景的来说,由于Unity运行时只会有一个场景呈现在大家眼前。所以就显得尤为适用场景之间的切换。
- 当一个对象的行为取决于它的状态,并且他必须在运行时根据状态改变他的行为时,就可以考虑使用状态模式了。
概念性的东西就这些,直接看项目
首先是State,他作为抽象类让具体状态继承
public abstract class State
{
public abstract void WriteProgram(Work w);
}
然后是,早上,中午,下午,晚上四个类
public class ForenoonState:State
{
public override void WriteProgram(Work w)
{
if (w.Hour < 12)
{
Debug.Log("当前时间:" + w.Hour + "点 上午工作,精神百倍");
}
else
{
w.SetState(new NoonState());
w.WriteProgram();
}
}
}
public class NoonState:State
{
public override void WriteProgram(Work w)
{
if (w.Hour < 13)
{
Debug.Log("当前时间:" + w.Hour + "点 饿了,午休;犯困,午休");
}
else
{
w.SetState(new AfternoonState());
w.WriteProgram();
}
}
}
public class AfternoonState:State
{
public override void WriteProgram(Work w)
{
if (w.Hour < 17)
{
Debug.Log("当前时间:" + w.Hour + "点 下午状态还不错,继续努力");
}
else
{
w.SetState(new EveningState());
w.WriteProgram();
}
}
}
public class EveningState:State
{
public override void WriteProgram(Work w)
{
if (w.Hour > 18)
{
Debug.Log("当前时间:" + w.Hour + "点 我不行了,要睡着了");
}
}
}
然后是工作类,调控全部的工作状态
public class Work
{
private State _current;
public Work()
{
_current=new ForenoonState();
}
private double _hour;
public double Hour
{
get { return _hour; }
set { _hour = value; }
}
public void SetState(State s)
{
_current = s;
}
public void WriteProgram()
{
_current.WriteProgram(this);
}
}
测试脚本
using System.Collections;
using System.Collections.Generic;
using DefaultNamespace;
using UnityEngine;
public class Test : MonoBehaviour {
private void Start () {
Work emergencyProject=new Work();
emergencyProject.Hour = 9;
emergencyProject.WriteProgram();
emergencyProject.Hour = 10;
emergencyProject.WriteProgram();
emergencyProject.Hour = 12;
emergencyProject.WriteProgram();
emergencyProject.Hour = 13;
emergencyProject.WriteProgram();
emergencyProject.Hour = 14;
emergencyProject.WriteProgram();
emergencyProject.Hour = 17;
emergencyProject.WriteProgram();
emergencyProject.Hour = 21;
emergencyProject.WriteProgram();
}
}
在Unity创建场景,在场景创建一个空物体,把Test脚本挂载在其上面
运行游戏
这时,我们增加需求:
- 出于安全考虑,超过21点,全体员工必须回家
- 18点之后,做完工作的可以提前回家
增加下班类
public class FuckingOutwork:State
{
public override void WriteProgram(Work w)
{
Debug.Log("下班了,溜了溜了");
}
}
更改工作类,增加结束工作字段
private bool _finish = false;
public bool Finish
{
get { return _finish; }
set { _finish = value; }
}
更改晚上工作类如下
public class EveningState : State
{
public override void WriteProgram(Work w)
{
if (w.Finish)
{
w.SetState(new FuckingOutwork());
w.WriteProgram();
}
else
{
if (w.Hour <= 21)
{
Debug.Log("当前时间:" + w.Hour + "点 我不行了,要睡着了");
}
else
{
w.SetState(new FuckingOutwork());
w.WriteProgram();
}
}
}
}
Test脚本增加一条22点的语句
emergencyProject.Hour = 22;
emergencyProject.WriteProgram();
再次运行
Test脚本更改如下
using System.Collections;
using System.Collections.Generic;
using DefaultNamespace;
using UnityEngine;
public class Test : MonoBehaviour {
private void Start () {
Work emergencyProject=new Work();
emergencyProject.Hour = 9;
emergencyProject.WriteProgram();
emergencyProject.Hour = 10;
emergencyProject.WriteProgram();
emergencyProject.Hour = 12;
emergencyProject.WriteProgram();
emergencyProject.Hour = 13;
emergencyProject.WriteProgram();
emergencyProject.Hour = 14;
emergencyProject.WriteProgram();
emergencyProject.Hour = 17;
emergencyProject.WriteProgram();
emergencyProject.Finish = true;
emergencyProject.WriteProgram();
emergencyProject.Hour = 21;
emergencyProject.WriteProgram();
emergencyProject.Hour = 22;
emergencyProject.WriteProgram();
}
}
再次运行
我们发现,增加的这两个判定条件需要改动的代码量很小。体现出了状态模式的优点。
理论差不多了解,那么我们就需要把它运用到实战中!请看下集