学习南梦宫的开发实例 状态管理的 一种写法笔记
一、状态管理的流程
状态管理主要有以下三个工作
(1) 迁移 :决定了状态该如何变化;
(2)初始化 :仅在每次状态迁移时执行一次;
(3)执行:是每帧都会对各个状态进行的处理;
重点在于一开始执行“迁移检测”。
二、实际游戏中使用的状态管理的代码示例如下
public enum STATUS {
NONE = -1,
STAND = 0, // 站立
DECLINE, //下降
ACCELERATE, //加速
ROTATE, //旋转
LEFT, //左
RIGHT, //右
}
public STATUS status = STATUS.NONE; //现在的状态
public STATUS next_status = STATUS.NONE; //下一次迁移的状态
public float step_timer = 0.0f; //统计迁移经过时间
public void Start () {
//初始化
this.next_status = STATUS.STAND;
}
public void Update () {
// (a)统计迁移到当前状态后经过的时间
this.step_timer += Time.deltaTime;
// ---------------------------------------------------------------- //
// (b)判断检测是否迁移到下一个状态
if (this.next_status == STATUS.NONE) {
switch (this.status) {
case STATUS.NONE:
{
this.next_status = STATUS.STAND;
}
break;
case STATUS.STAND:
{
//按下左 Shift 键 开始下落
if (Input.GetKeyDown (KeyCode.LeftShift)) {
this.next_status = STATUS.DECLINE;
}
}
break;
case STATUS.DECLINE:
{
//下落状态下,可以迁移的状态
if (Input.GetKeyDown (KeyCode.W)) {
this.next_status = STATUS.ROTATE;
}
if (Input.GetKeyDown (KeyCode.S)) {
this.next_status = STATUS.ACCELERATE;
}
if (Input.GetKeyDown (KeyCode.A)) {
this.next_status = STATUS.LEFT;
}
if (Input.GetKeyDown (KeyCode.D)) {
this.next_status = STATUS.RIGHT;
}
}
break;
case STATUS.ACCELERATE:
{
}
break;
case STATUS.ROTATE:
{
}
break;
case STATUS.LEFT:
{
}
break;
case STATUS.RIGHT:
{
}
break;
}
}
// ---------------------------------------------------------------- //
//(c)状态迁移时的初始化
if (this.next_status != STATUS.NONE) {
switch (this.next_status) {
case STATUS.STAND:
{
Debug.Log ("播放站立动画");
}
break;
case STATUS.DECLINE:
{
}
break;
case STATUS.ACCELERATE:
{
}
break;
case STATUS.ROTATE:
{
}
break;
case STATUS.LEFT:
{
}
break;
case STATUS.RIGHT:
{
}
break;
}
//(d)更新 现在的状态
this.status = this.next_status;
this.next_status = STATUS.NONE;
this.step_timer = 0.0f;
}
// ---------------------------------------------------------------- //
//(e)各个状态的执行处理
switch (this.status) {
case STATUS.STAND:
{
}
break;
case STATUS.DECLINE:
{
}
break;
case STATUS.ACCELERATE:
{
}
break;
case STATUS.LEFT:
{
}
break;
case STATUS.RIGHT:
{
}
break;
case STATUS.ROTATE:
{
}
break;
}
}
上述代码中说明大致流程 : this.status 指现在的状态, this.next_status 表示下一次迁移的状态。当 this.next_status 的值 为 STATUS.NONE时,将不发生迁移。
(a)首先,更新迁移到当前状态后已经经过的时间。比如在“经过一定的时间后再迁移到其他状态”等情况下,会用到这个值。
(b)然后执行状态迁移判断,之所以要判断 this.next_status 是否等于STATUS.NONE,是为了能让外部对状态的迁移进行控制。
(c)状态发生迁移后,开始新状态的初始化处理。
(d)在初始化的最后,更新当前状态的 this.status 的值,清空 this.next_status 的值。注意这里如果没有把 this.next_status 清空成 STATUS.NONE ,将导致下一帧继续发生迁移。最后将状态前后经过的时间设置为0.
(e)最后,执行各个状态。
三、小结
通过这个例子,我们可以很好的理解“状态管理”的基本思路。如果读者向更一步了解状态的相关运用,可以试着 敲一下代码,并添加动能,比如 旋转:
(1) 旋转结构
//旋转状态的数据结构
public struct ActionRotate {
public STATUS prevoius_status; //旋转前的状态
public bool is_key_released; //旋转后,是否松开w键?
}
public ActionRotate action_rotate; //旋转行为
(2) 初始化
case STATUS.ROTATE:
{
this.action_rotate.is_key_released = false;
this.action_rotate.prevoius_status = this.status;
Debug.Log ("初始化 旋转 比如:调用协程旋转方法 或者 播放旋转动画");
}
break;
(3) 执行处理
case STATUS.ROTATE:
{
// 旋转中松开按键处理
do {
if (Input.GetKeyUp (KeyCode.W)) {
this.action_rotate.is_key_released = true;
Debug.Log ("停止 旋转或者 动画");
break;
}
if (this.action_rotate.is_key_released) {
this.status = STATUS.DECLINE;
break;
}
} while (false);
}
break;