设计模式-状态模式的简单实现

状态模式包括Context、State和ConcreteState角色。Context维护一个具体状态对象并委托行为,State定义相关行为接口,ConcreteState实现这些行为。本文通过一个简单的状态模式示例,演示如何使用该模式实现场景跳转管理,例如StartScene、MainScene和BattleScene的切换,并提供了状态枚举类、状态父类及具体场景类的实现。
摘要由CSDN通过智能技术生成

状态模式包括以下几种角色:

Context(状态持有类): 它定义了客户程序需要的接口并维护一个具体状态角色的实例,将与状态相关的操作委托给当前的Concrete State对象来处理。

State(抽象状态类): 定义一个接口以封装使用上下文环境的的一个特定状态相关的行为。

ConcreteState(具体状态类): 实现抽象状态定义的接口。

在这里插入图片描述
状态模式的原型

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class StateModePrototype : MonoBehaviour
{
   void  Start()
    {
        Context context = new Context();
        context.SetState(new StateA(context));
        context.Execute(-1);
        context.Execute(1);
        context.Execute(-2);
    }
}
/// <summary>
/// 状态持有者
/// </summary>
public class Context
{
    private Istate state;
    public void SetState(Istate _state)
    {
        this.state = _state;
    }
    public void Execute(int arg)
    {
        state.Execute(arg);
    }
}
/// <summary>
/// 状态接口
/// </summary>
public interface Istate
{
    void Execute(int arg);//这个参数需要根据实际确认
}

public class StateA : Istate
{
    private Context context;
    public StateA(Context _context)
    {
        context = _context;
    }
    public void Execute(int arg)
    {
        if (arg<=0)
        {
            context.SetState(new StateB(context));
            Debug.Log("A->B");
        }
    }
}
public class StateB : Istate
{
    private Context context;
    public StateB(Context _context)
    {
        context = _context;
    }
    public void Execute(int arg)
    {
        if (arg>0)
        {
            context.SetState(new StateA(context));
            Debug.Log("B->A");
        }
    }
}

一个简单状态模式的demo
demo:利用状态模式实现场景的跳转管理
state: StartScene(开始场景),MainScene(主场景),BatterScene(战斗场景)
枚举类

  public enum SceneName
{
    StartScene,
    MainScene,
    BatterScene,
}

状态父类

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ISceneState
{
	protected SceneController sceneController;//状态所属的管理者
	private string sceneName = string.Empty;//跳转场景的名字

	public string SceneName { get => sceneName; }

	public ISceneState(SceneController _sceneController,SceneName _sceneName)
	{
		sceneController = _sceneController;
		sceneName = _sceneName.ToString();
	}

	public virtual void SceneEnter() { }//进入场景时执行的方法 执行一次
	public virtual void SceneStay() { }//在场景中会一直执行  每一帧都会执行
	public virtual void SceneExit() { }//退出当前场景时执行  执行一次
}

具体的开始游戏的场景(一波播放开始的加载动画界面)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class StartScene : ISceneState
{
    private float nextTime = 2;
    private float waitTimer=0;
    public StartScene(SceneController _sceneController) : base(_sceneController, global::SceneName.StartScene)
    {
    }
    public override void SceneEnter()
    {
        base.SceneEnter();
        Debug.Log("进入StartScene");
    


    }

    public override void SceneStay()
    {
        base.SceneStay();
        Debug.Log("处于StartScene");
        //2s后进入MainScene
        waitTimer += Time.deltaTime;
        if (waitTimer>=nextTime)
        {
            sceneController.SetSceneState(new MainScene(sceneController), true);

        }

    }

    public override void SceneExit()
    {
        base.SceneExit();
        Debug.Log("退出StartScene");
    }
}

具体的主场景类

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class MainScene : ISceneState
{
    private Button enterBatterBut;
    public MainScene(SceneController _sceneController) : base(_sceneController, global::SceneName.MainScene)
    {
    }
    public override void SceneEnter()
    {
        base.SceneEnter();
        Debug.Log("进入MainScene");
        enterBatterBut = GameObject.Find("EnterBatterButton").GetComponent<Button>();
        enterBatterBut.onClick.AddListener(OnClickEnterBatterBut) ; 
    }
    public override void SceneStay()
    {
        base.SceneStay();
        Debug.Log("处于MainScene");
    }

    public override void SceneExit()
    {
        base.SceneExit();
        Debug.Log("退出MainScene");
    }

    private void OnClickEnterBatterBut()
    {
        sceneController.SetSceneState(new BatterScene(sceneController), true);
    }
}

具体战斗场景类

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class BatterScene : ISceneState
{
    public BatterScene(SceneController _sceneController) : base(_sceneController, global::SceneName.BatterScene)
    {
    }
    public override void SceneEnter()
    {
        base.SceneEnter();
        Debug.Log("进入BatterScene");
       
    }
    public override void SceneStay()
    {
        base.SceneStay();
        Debug.Log("处于BatterScene");
    }
    public override void SceneExit()
    {
        base.SceneExit();
        Debug.Log("退出BatterScene");
    }
}

状态的持有(控制)类Context

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class SceneController
{
    private ISceneState sceneState;
    private AsyncOperation ao;
    private bool isFirstEnterScene=true;
    public void SetSceneState(ISceneState _sceneState,bool isLoadScene)
    {
        if (sceneState!=null)
        {
            sceneState.SceneExit();//执行上一个状态的退出时函数
        }
        sceneState = _sceneState;
        if (isLoadScene)
        {
            ao = SceneManager.LoadSceneAsync(sceneState.SceneName);
            isFirstEnterScene = true;
        }
        else
        {
            sceneState.SceneEnter();//刚加入场景时执行进入场景的方法
            isFirstEnterScene = false;
        }
      
      
    }
    public void SceneStateUpdate()
    {//isFirstEnterScene 防止进入场景后 一直调用enter中的方法
        if (isFirstEnterScene &&ao != null&&ao.isDone)
        {
            sceneState.SceneEnter();//刚加入场景时执行进入场景的方法
            isFirstEnterScene = false;

        }
        if (sceneState!=null)
        {
            sceneState.SceneStay();//在状态中 每一帧都执行SceneStay
        }
        
    }


}

调用类

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GameLoop : MonoBehaviour
{
    private SceneController sceneController;
    private void Awake()
    {
     
        DontDestroyOnLoad(gameObject);
       
    }
    void Start()
    {
        sceneController = new SceneController();
        sceneController.SetSceneState(new StartScene(sceneController),false);
      
    }

    // Update is called once per frame
    void Update()
    {
        if (sceneController!=null)
        {
            sceneController.SceneStateUpdate();
        }
       
    }
}

效果演示
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值