状态模式在游戏开发中的应用

状态模式

在状态模式中,类的行为是基于它的状态改变的。这种类型的设计模式属于行为模式。
我们通过创建一个对象来随着状态的改变而进行不同的行为。

意图

允许对象在内部状态发生改变时改变它的行为,对象看起来好像修改了它的类。主要用来解决:对象的行为依赖于它的状态,并且可以根据它的状态改变而改变它的行为。

需求描述:

我们在游戏中控制一个角色,我们需要操作键盘,按下不同的键来改变当前角色的状态,比如控制角色奔跑、跳跃、下蹲、等等。各种状态之间存在这样的关联。默认状态为Idle,(A->B表示由A状态可以变换到B状态)Idle->Jump、Idle->Run、Idle->Squat】、【Jump->Idle】、【Run->Jump、Run->Idle、Run->Squat】、【Squat->Idle】


在这里插入图片描述

状态模式的结构
  1. 抽象状态角色:提供一个接口,用于封装特定状态对应的行为。
  2. 具体状态角色:实现抽象状态角色对应的行为。
  3. 控制器上下文:维护当前状态,并提供触发相应状态的条件;比如:不同的键盘输入,切换不同的动画状态。

首先,定义抽象基类如下:

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:


在这里插入图片描述

没有更多推荐了,返回首页