状态模式
在状态模式中,类的行为是基于它的状态改变的。这种类型的设计模式属于行为模式。
我们通过创建一个对象来随着状态的改变而进行不同的行为。
意图
允许对象在内部状态发生改变时改变它的行为,对象看起来好像修改了它的类。主要用来解决:对象的行为依赖于它的状态,并且可以根据它的状态改变而改变它的行为。
需求描述:
我们在游戏中控制一个角色,我们需要操作键盘,按下不同的键来改变当前角色的状态,比如控制角色奔跑、跳跃、下蹲、等等。各种状态之间存在这样的关联。默认状态为Idle,(A->B表示由A状态可以变换到B状态)Idle->Jump、Idle->Run、Idle->Squat】、【Jump->Idle】、【Run->Jump、Run->Idle、Run->Squat】、【Squat->Idle】。
状态模式的结构
- 抽象状态角色:提供一个接口,用于封装特定状态对应的行为。
- 具体状态角色:实现抽象状态角色对应的行为。
- 控制器上下文:维护当前状态,并提供触发相应状态的条件;比如:不同的键盘输入,切换不同的动画状态。
首先,定义抽象基类如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
public abstract class BaseState{
public abstract void Handle(PlayerController playerController);
}
实现具体的角色状态类如下:
- Idle状态
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class IdleState : BaseState {
public IdleState () {
}
public override void Handle (PlayerController playerController) {
Debug.Log ("我在Idle");
OnEnter (playerController);
}
private void OnEnter (PlayerController playerController) {
playerController._currentState = this;
playerController.playerState = PlayerState.Idle;
Debug.Log ("现在的状态是:" + playerController._currentState);
}
}
- Jump状态
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class JumpState : BaseState {
public JumpState()
{
}
public override void Handle (PlayerController playerController) {
Debug.Log ("我在Jump");
OnEnter(playerController);
}
private void OnEnter (PlayerController playerController) {
playerController._currentState = this;
playerController.playerState=PlayerState.Jump;
Debug.Log ("现在的状态是:" + playerController._currentState);
}
}
- Run状态
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RunState : BaseState
{
public RunState()
{
}
public override void Handle(PlayerController playerController)
{
Debug.Log("我Run");
OnEnter(playerController);
}
private void OnEnter(PlayerController playerController)
{
playerController._currentState=this;
playerController.playerState=PlayerState.Run;
Debug.Log("现在的状态是:"+playerController._currentState);
}
}
- Squat状态
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SquatState : BaseState {
public SquatState () {
}
public override void Handle (PlayerController playerController) {
Debug.Log ("我在Squat");
OnEnter(playerController);
}
private void OnEnter (PlayerController playerController) {
playerController._currentState = this;
playerController.playerState=PlayerState.Squat;
Debug.Log ("现在的状态是:" + playerController._currentState);
}
}
- 控制器上下文实现:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public enum PlayerState {
Idle, //站立状态
Jump, //跳跃状态
Run, //奔跑状态
Squat //下蹲状态
}
public class PlayerController : MonoBehaviour {
public BaseState _currentState;
public PlayerState playerState;
private BaseState idleState;
private BaseState jumpState;
private BaseState runState;
private BaseState squatState;
void Start () {
//默认的状态为Idle状态
idleState = new IdleState ();
jumpState = new JumpState ();
runState = new RunState ();
squatState = new SquatState ();
_currentState = new IdleState ();
playerState = PlayerState.Idle;
}
void Update () {
switch (playerState) {
case PlayerState.Idle:
if (Input.GetKeyDown (KeyCode.Space))
{ _currentState = jumpState; _currentState.Handle (this); }
if (Input.GetKeyDown (KeyCode.LeftControl))
{ _currentState = squatState; _currentState.Handle (this); }
if (Input.GetAxis ("Horizontal") != 0)
{ _currentState = runState; _currentState.Handle (this); }
break;
case PlayerState.Jump:
if (!Input.GetKey (KeyCode.Space))
{ _currentState = idleState; _currentState.Handle (this); }
break;
case PlayerState.Run:
if (Input.GetKeyDown (KeyCode.Space))
{ _currentState = jumpState; _currentState.Handle (this); }
if (Input.GetKeyDown (KeyCode.LeftControl))
{ _currentState = squatState; _currentState.Handle (this); }
if (Input.GetAxis ("Horizontal") == 0)
{ _currentState = idleState; _currentState.Handle (this); }
break;
case PlayerState.Squat:
if (!Input.GetKey (KeyCode.LeftControl))
{ _currentState = idleState; _currentState.Handle (this); }
break;
}
}
}
扫码关注获取完整Demo: