Unity3D游戏开发——编程实现游戏管理器

本篇简介

  • 本篇介绍了如何将上一篇的设计模式思想运用到实际的开发过程中。

脚本文件

  • (1)IGameManager:这个接口存在声明了一个属性(一个拥有getter函数的变量,属性的类型是ManagerStatus,一个枚举)和一个方法,它们都要被任何实现这个接口的类实现。定义了status属性,可以从任何地方获取状态(getter方法是公有方法),但是只能在脚本中设置状态(setter方法是私有方法).(ps:一个接口本身不会做任何事情,它存在的意义仅仅是将代码结构约束到其他类身上)
  • (2)ManagerStatus:这是一个几乎没有代码的文件,列出了管理器所有可能的状态(限定了status属性只能是里面列出的状态之一)。
  • (3)PlayerManager与InventoryManager:前者为人物管理器,后者为库存管理器。它们都继承自类MonoBehaviour且实现了IGameManager定义的结构。
  • (4)Managers:管理器的管理器。

状态转化

  • 在所有的管理器中,初始化(InventoryManager没有做任何事情,而PlayerManager设置了一些值)一旦完成,status将被设置为Started。
  • 但是数据模块的初始化中可能有一些长线任务(例如加载所保存的数据),在初始化时,Startup()将运行这些任务,设置管理器的状态为Initializing(初始化中)。当完成后,再将status转化为Started。

IGameManger的脚本代码

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

public interface IGameManager 
{
    ManagerStatus status { get; } //这是一个我们需要定义的枚举

    void Startup();  //这个方法的目的是处理管理器的初始化

}

ManagerStatus的脚本代码

public enum ManagerStatus
{
    Shutdown,  //关机
    Initializing,  //正在初始化
    Started  //开始启动
}

PlayerManager的脚本代码

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

///<summary>
///人物管理脚本
///</summary>

public class PlayerManager : MonoBehaviour, IGameManager    //继承一个类并实现一个接口
{
    public ManagerStatus status
    {
        get;
        private set;  //status只读,不能在外部设置,内部可读写
    }

    public int health  //人物健康值
    {
        get;
        private set;
    }

    public int maxHealth  //人物最高健康值
    {
        get;
        private set;
    }

    public void Startup()
    {
        Debug.Log("PlayerManager starting ...");
        health = 50;   //初始化值
        maxHealth = 100;

        status = ManagerStatus.Started;
    }

    public void ChangeHealth(int value)
    {
        health += value;
        if (health > maxHealth)
        {
            health = maxHealth;
        }
        else if (health < 0)  //健康值最小为0
        {
            health = 0;
        }

        Debug.Log("Health:" + health + "/" + maxHealth);
    }
}

InventoryManager的脚本代码

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

///<summary>
///库存管理脚本
///</summary>

public class InventoryManager : MonoBehaviour, IGameManager
{
    public ManagerStatus status  //这个属性可以从任何地方获取,但只能在这个脚本中设置
    {
        get;
        private set;
    }

    public void Startup()  
    {
        Debug.Log("InventoryManager starting ...");//任何长任务在这里启动
        status = ManagerStatus.Started;   //如果是长任务,状态改变为"Initializing"
    }

}

Managers的脚本代码

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

///<summary>
///管理器的管理器
///</summary>

[RequireComponent(typeof(PlayerManager))]  //自动添加管理器,确保存在不同的管理器
[RequireComponent(typeof(InventoryManager))]

public class Managers : MonoBehaviour
{
    public static PlayerManager Player //其他代码用来访问管理器的静态属性
    {
        get;
        private set;
    }
    public static InventoryManager Inventory
    {
        get;
        private set;
    }

    private List<IGameManager> _startSequence;  //启动时要遍历的管理器列表

    void Awake()  //列出了启动序列,然后启动协同程序来运行所有的管理器
    {
        Player = GetComponent<PlayerManager>();
        Inventory = GetComponent<InventoryManager>();

        _startSequence = new List<IGameManager>();  //创建了List对象,用List.Add的方法来添加管理器。列表对象与数组相似,以一种具体的类型声明,把一系列元素依次存入,但可在创建后改变大小。
        _startSequence.Add(Player);
        _startSequence.Add(Inventory);

        StartCoroutine(StartupManagers());  //异步启动序列
    }

    private IEnumerator StartupManagers()
    {
        foreach (IGameManager manager in _startSequence)
        {
            manager.Startup();
        }
        yield return null;

        int numModules = _startSequence.Count;
        int numReady = 0;

        while (numReady < numModules)  //循环至所有管理器都启动为止
        {
            int lastReady = numReady;
            numReady = 0;

            foreach (IGameManager manager in _startSequence)
            {
                if (manager.status == ManagerStatus.Started)
                {
                    numReady++;
                }
            }
            if (numReady > lastReady)
                Debug.Log("progress:" + numReady + "/" + numModules);
            yield return null;
        }

        Debug.Log("All managers started up");
    }

}

参考资料

posted @ 2019-04-04 23:06  苏木木木  阅读(1138)  评论(0编辑  收藏  举报