设计模式 -(状态模式)游戏场景的转换

定义

状态模式简单定义就是类的行为是基于它的状态改变的。
例如在王者荣耀中裴擒虎拥有人形态和虎形态。当玩家决定转换形态时,裴擒虎会进入虎形态,这时候裴擒虎会以虎形态来表现其行为,包含移动攻击和技能,当玩家决定转换为人形时,裴擒虎就会复原到人形态。所以这种转换可以看作为裴擒虎的一种内部状态的转换。通过外形的变化导致角色表现出另外一种的行为模式,但是无论怎样转换,操作的角色还是裴擒虎。

组成部分

一般设计状态模式分为三个部分,Context, Start, ConcreteState
Context(状态拥有者)是一个具有“状态”属性的类,可以定制相关的接口,让外界能够得知状态的修改,通过操作让状态改变。有状态属性的类,例如:角色的攻击,施法等状态。
State(状态接口类)制定状态的接口,负责规范Context的下要的表现行为。
ConcreteState(具体状态类)1.继承自State。2.实现Context在状态下特有的行为。如:实现角色在前行的状态下行动变缓,模型半透明。

游戏场景切换的应用

设计的脚本:
1.ISceneState场景类的接口,定义场景的转换和执行时需要调用的方法。
2.StartState,MainState,BattleState 作为场景执行的操作类。
3.SceneContext 场景状态的拥有者,保持当前游戏场景状态。

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

public class ISceneState
{
    private SceneContext sceneContext;


    public ISceneState(SceneContext sceneContext)
    {
        this.sceneContext = sceneContext;
    }

    public virtual void SceneBegin()
    {
        //加载游戏资源
    }

    public virtual void SceneEnd()
    {
        //释放游戏资源
    }

    public virtual void SceneUpdate()
    {
        //场景更新逻辑
    }
}

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

public class StartState : ISceneState
{
    private SceneContext sceneContext;
    public StartState(SceneContext sceneContext):base(sceneContext)
    {
        this.sceneContext = sceneContext;
    }

    public override void SceneBegin()
    {
        Debug.Log("加载StartState");
        this.sceneContext.SetState(new MainState(sceneContext), "MainScene");
    }

    public override void SceneEnd()
    {
        Debug.Log("释放StartState");
    }

    public override void SceneUpdate()
    {

    }
}

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

public class MainState : ISceneState
{
    private SceneContext sceneContext;
    public MainState(SceneContext sceneContext):base(sceneContext)
    {
        this.sceneContext = sceneContext;
    }

    public override void SceneBegin()
    {
        Debug.Log("加载MainState");
        this.sceneContext.SetState(new BattleState(sceneContext), "BattleScene");
    }

    public override void SceneEnd()
    {
        Debug.Log("释放MainState");
    }


    public override void SceneUpdate()
    {

    }
}

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

public class BattleState : ISceneState
{
    private SceneContext sceneContext;
    public BattleState(SceneContext sceneContext):base(sceneContext)
    {
        this.sceneContext = sceneContext;
    }

    public override void SceneBegin()
    {
        Debug.Log("加载BattleState");
    }

    public override void SceneEnd()
    {
        Debug.Log("释放BattleState");
    }


    public override void SceneUpdate()
    {

    }
}

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

public class SceneContext : MonoBehaviour
{
    private ISceneState sceneState;
    private bool isLoadBegin;
    private AsyncOperation asyncOperation;

    public void SetState(ISceneState sceneState, string loadSceneName)
    {
        if (this.sceneState != null)
        {
            this.sceneState.SceneEnd();   
        }
        this.sceneState = sceneState;
        isLoadBegin = false;
        LoadScene(loadSceneName);
    }

    private void LoadScene(string loadName)
    {
        if (!(loadName == null || loadName.Length == 0))
        {
            asyncOperation = SceneManager.LoadSceneAsync(loadName);
        }
    }

    public void Update()
    {
        if (this.sceneState == null || (asyncOperation != null && asyncOperation.isDone == false))
            return;

        if (isLoadBegin == false)
        {
            isLoadBegin = true;
            this.sceneState.SceneBegin();
        }
        this.sceneState.SceneUpdate();
    }
}

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

public class Main : MonoBehaviour
{
    private SceneContext sceneContext;
    private void Awake()
    {
        GameObject.DontDestroyOnLoad(this.gameObject);
    }
    private void Start()
    {
        sceneContext = new SceneContext();
        sceneContext.SetState(new StartState(sceneContext), "");
    }

    private void Update()
    {
        sceneContext.Update();
    }
}

执行结果

在这里插入图片描述

优缺点

在场景设计中,属于“产出较少的状态类,但是如果有大量状态的系统时,就会遇到产出过多状态类的情况,会伴随类爆炸的问题。但是相比于传统的switch在后续的维护来看,仍然有优势。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值