游戏中的设计模式一:单例模式与状态模式

发表于2018-03-25
评论0 2.3k浏览
这个系列主要是和大家介绍游戏中常用的设计模式,然后用一些具体的Unity3d游戏实例让大家感受这些设计模式和它们的作用,下面就介绍这个系列的第一篇文章,单例模式与状态模式。

在游戏角色的各个战斗状态(idle,attack,run……)、场景状态(开始场景、战斗场景、主城场景……)都可以使用设计模式来管理组织,本文通过一个实例介绍使用状态模式来创建管理游戏中的多个游戏场景。

案例介绍

在游戏开始场景有两个按钮,点击一个按钮进入战斗场景,点击另外一个按钮进入主城场景
案例虽简单,但是已经满足我们本文的目标

编写代码

创建一个场景状态基类
using System.Collections;  
using System.Collections.Generic;  
using UnityEngine;  
public class ISceneState  
{  
    protected string mSceneName { get; set; }  
    public ISceneState(string scennName)  
    {  
        this.mSceneName = scennName;  
    }  
    public virtual void StartScene() { }  
    public virtual void UpadteScene() { }  
    public virtual void EndScene() { }  
}  

接下来介绍使用一个对象来管理各个场景。
其中使用单例模式,可以理解为实例一个管理者,由这个管理者来切换我们的目标场景;
设计成单例模式的作用的话方便我们统一管理,增强代码灵活性调用简单,避免不必要的内存消耗等
using System;  
using System.Collections.Generic;  
using System.Text;  
class SceneStateManager  
{  
    //单例模式  
    private static SceneStateManager _instance;  
    public static SceneStateManager GetInstacne  
    {  
        get  
        {  
            if (_instance == null)  
            {  
                _instance = new SceneStateManager();  
            }  
            return _instance;  
        }  
    }  
    private ISceneState mState { get; set; }  
    public void SetSceneState(ISceneState state)  
    {  
        //对上一个场景状态退出处理  
        if (mState != null)  
        {  
            mState.EndScene();  
        }  
        mState = state;  
        //对新场景状态进行开始处理  
        if (mState != null)  
        {  
            mState.StartScene();  
        }  
    }  
    public void UpdateSceneState()  
    {  
        if (mState != null)  
        {  
            mState.UpadteScene();  
        }  
    }  
}  

接下来就是创建各个场景类了,场景类都基础自ISceneState类
开始场景类StartSceneState
using System;  
using System.Collections.Generic;  
using System.Text;  
using UnityEngine;  
using UnityEngine.UI;  
class StartSceneState : ISceneState  
{  
    public StartSceneState() : base("StartScene") { }  
    public override void StartScene()  
    {  
        GameObject.FindGameObjectWithTag("Battle").GetComponent<Button>().onClick.AddListener(OnBtnBattle);  
        GameObject.FindGameObjectWithTag("MainMenu").GetComponent<Button>().onClick.AddListener(OnBtnMainMenu);  
    }  
    private void OnBtnBattle()  
    {  
        SceneStateManager.GetInstacne.SetSceneState(new BattleScene());  
    }  
    private void OnBtnMainMenu()  
    {  
        SceneStateManager.GetInstacne.SetSceneState(new MainMenuSceneState());  
    }  
}  

战斗场景类BattleScene
using System;  
using System.Collections.Generic;  
using System.Text;  
using UnityEngine.SceneManagement;  
class BattleScene : ISceneState  
{  
    public BattleScene() : base("BattleScene")  
    {  
    }  
    public override void StartScene()  
    {  
        SceneManager.LoadScene(this.mSceneName);  
    }  
}  

主城场景类MainMenuSceneState
using System;  
using System.Collections.Generic;  
using System.Text;  
using UnityEngine.SceneManagement;  
class MainMenuSceneState : ISceneState  
{  
    public MainMenuSceneState() : base("MainMenuScene")  
    {  
    }  
    public override void StartScene()  
    {  
        SceneManager.LoadScene(this.mSceneName);  
    }  
}  
好了各个场景都已经实现好了

接下来是创建一个类用于调用管理类(SceneStateManager),其继承自Monobehavior,将其挂载到一个游戏对象上。
代码如下
using System;  
using System.Collections.Generic;  
using System.Text;  
using UnityEngine;  
class GameContext : MonoBehaviour  
{  
    private void Start()  
    {  
        SceneStateManager.GetInstacne.SetSceneState(new StartSceneState());  
    }  
    private void Update()  
    {  
        SceneStateManager.GetInstacne.UpdateSceneState();  
    }  
}  

总结

创建一个单例管理类,用于管理场景之间的切换,每个场景都拥有自己的一个状态类来处理本场景状态中的逻辑时间。

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引