您的位置:首页 > 其它

游戏简单控制逻辑 一个轻量级的状态机

2015-04-08 05:01 435 查看
出处:http://blog.csdn.net/u010019717

author:孙广东 时间:2015.3.25

关于状态机这种设计模式不用多介绍了,网上有很多这方面的介绍,特别是FSM。

现在是我实现一个轻量级的状态机。

[csharp] view
plaincopyprint?





using System;

using System.Collections.Generic;

namespace Gamelogic

{

/**

一个轻量级的状态机。

要使用它:

-# 定义您自己的label。枚举Enums可能是最好的选择。

-# 构造一个新的状态机state machin,通常是在 MonoBehaviour 的Start方法中。

-# 添加的各种状态和对应的delegates。

-# 从 MonoBehaviour 的Update方法调用状态机Update方法。

-# 在状态机transition转换状态时调用 ChangeState 方法(你可以调用此方法,从一个state delegates,或任何其他地方)

-# 状态发生变化时,对现有状态执行关闭 OnStop,然后OnStart开启新状态,之后新的状态每帧更新中调用 OnUpdate 方法

*/

public sealed class StateMachine<TLabel>

{

private class State

{

public readonly Action onStart;

public readonly Action onUpdate;

public readonly Action onStop;

public readonly TLabel label;

public State(TLabel label, Action onStart, Action onUpdate, Action onStop)

{

this.onStart = onStart;

this.onUpdate = onUpdate;

this.onStop = onStop;

this.label = label;

}

}

private readonly Dictionary<TLabel, State> stateDictionary;

private State currentState;

/**

Returns the label of the current state.

*/

public TLabel CurrentState

{

get { return currentState.label; }

/**@version1_2*/

set { ChangeState(value); }

}

/**

Constructs a new StateMachine.

*/

public StateMachine()

{

stateDictionary = new Dictionary<TLabel, State>();

}

/**

Adds a state, and the delegates that should run

when the state starts, stops,

and when the state machine is updated.

Any delegate can be null, and wont be executed.

*/

public void AddState(TLabel label, Action onStart, Action onUpdate, Action onStop)

{

stateDictionary[label] = new State(label, onStart, onUpdate, onStop);

}

/**

Changes the state from the existing one to the state with the given label.

*/

private void ChangeState(TLabel newState)

{

if (currentState != null && currentState.onStop != null)

{

currentState.onStop();

}

currentState = stateDictionary[newState];

if (currentState.onStart != null)

{

currentState.onStart();

}

}

/**

This method should be called every frame.

*/

public void Update()

{

if (currentState != null && currentState.onUpdate != null)

{

currentState.onUpdate();

}

}

}

}

使用的例子 很简单,cube的两种状态转换。 每种状态有不同的行为表现:





[csharp] view
plaincopyprint?





using System.Collections;

using UnityEngine;

namespace Gamelogic.Examples

{

public class Cube : MonoBehaviour

{

public enum CubeStates

{

Swivel,

MoveStraight

}

private StateMachine<CubeStates> stateMachine;

private float moveSpeed = 1;

private float switchTime = 3;

private float swivelSpeed = 2;

public void Start()

{

stateMachine = new StateMachine<CubeStates>();

stateMachine.AddState(CubeStates.Swivel, OnSwivelStart, OnSwivelUpdate, OnSwivelStop);

stateMachine.AddState(CubeStates.MoveStraight, null, OnMoveStraightUpdate, null);

stateMachine.CurrentState = CubeStates.MoveStraight;

StartCoroutine(SwitchStates());

}

public IEnumerator SwitchStates()

{

while (true)

{

stateMachine.CurrentState = CubeStates.Swivel;

yield return new WaitForSeconds(switchTime);

stateMachine.CurrentState = CubeStates.MoveStraight;

yield return new WaitForSeconds(switchTime);

}

}

public void Update()

{

stateMachine.Update();

}

public void OnGUI()

{

GUILayout.TextField(stateMachine.CurrentState.ToString());

}

public void OnMoveStraightUpdate()

{

float dx = -Time.deltaTime * moveSpeed;

transform.TranslateX(dx);

}

public void OnSwivelUpdate()

{

float dx = Time.deltaTime*moveSpeed;

float y = Mathf.Sin(swivelSpeed * transform.position.x * 2 * Mathf.PI/switchTime);

transform.TranslateX(dx);

transform.SetY(y);

}

public void OnSwivelStart()

{

GetComponent<Renderer>().material.color = Color.red;

}

public void OnSwivelStop()

{

GetComponent<Renderer>().material.color = Color.green;

transform.SetY(0); //recallibrate

}

}

}

就是这样的很简单的状态机。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: