游戏运行流程

流程(Procedure)

游戏的运行流程(Procedure)由ProcedureManager类进行管理,这也是框架的入口。

在Unity的生命流程的Start阶段,ProcedureManager会检索所有IProcedure的实现类。

不同的IProcedure代表了不同的游戏运行的状态,标志着游戏正处于一个什么状态。

框架内预设的IProcedure的实现类如下:

  • VMFrameworkInitializationDoneProcedure 框架核心加载完毕

  • GameInitializationDoneProcedure 游戏加载完毕

  • MainMenuProcedure 主菜单流程

  • ServerRunningProcedure 服务器运行流程

  • ClientRunningProcedure 客户端运行流程

流程如下:

VMFrameworkInitializationDoneProcedure->GameInitializationDoneProcedure-> MainMenuProcedure

之后有两个分支:

-> ServerRunningProcedure

-> ClientRunningProcedure

如果你开启此框架的网络扩展的话,在通过Fishnet启动服务器或客户端的时候,他会自动进入ServerRunningProcedure或ClientRunningProcedure。

值得注意的是管理游戏流程的并不是传统的状态机,游戏可以同时处于多个流程,比如同时处于ServerRunningProcedure和ClientRunningProcedure,这代表游戏作为Host在运行。

加载器(IInitializer)

加载器用来抽象一个加载过程,比如当游戏进入一个流程(Procedure)时,需要依据优先级调用一系列的函数,使用加载器来提供每个需要在加载时调用的函数以及这个函数对应的调用顺序。

调用顺序为整数,值越小,此函数越先调用。

常用的优先级预设为:

https://github.com/VMware233/VMFramework/blob/main/Assets/VMFramework/Main/Procedures/Initializer/InitializationOrder.cs
namespace VMFramework.Procedure
{
    public enum InitializationOrder
    {
        BeforeInitStart = 0,
        InitStart = 1000,
        PreInit = 2000,
        Init = 3000,
        PostInit = 4000,
        InitComplete = 5000,
        AfterInitComplete = 6000
    }
}

IGameInitializer

游戏加载器(IGameInitializer)是一个接口,继承自上面的接口IInitializer,用来表示一个游戏运行时的加载器(用来与在纯编辑器里的加载器IEditorInitializer作区分)。

可以通过GameInitializerRegister这个Attribute,将一个IGameInitializer挂载到任意一个IProcedure上,这样游戏在进入(OnEnter)退出(OnExit)这个IProcedure时就会运行挂载在这个IProcedure上面的IGameInitializer。

具体例子见 IGameInitializer

框架内置的加载器

进入VMFrameworkInitializationDoneProcedure时触发的加载器

按运行顺序:

BeforeInitStart阶段:

InitStart阶段:

PreInit阶段:

Init阶段:

PostInit阶段:

InitComplete阶段:

进入GameInitializationDoneProcedure时触发的加载器

没有特定阶段,视具体提供的加载顺序和函数而定:

Init阶段:

InitComplete阶段:

管理器创建、单例创建(IManagerBehaviour)

https://github.com/VMware233/VMFramework/blob/main/Assets/Examples/Procedure/BasicManagerBehaviour.cs
using VMFramework.Procedure;

namespace VMFramework.Examples
{
    [ManagerCreationProvider("Demo")]
    public sealed class BasicManagerBehaviour : ManagerBehaviour<BasicManagerBehaviour>
    {
        protected override void OnBeforeInitStart()
        {
            base.OnBeforeInitStart();
            
            // Add any code here that needs to be executed to initialize the manager.
        }
    }
}

如上述代码所示,带有ManagerCreationProvider这个Attribute的class都会被在游戏的一开始自动挂到场景里的CORE下的一个名为“Demo”的GameObject上(如果已经挂载则不会重复挂载,具体挂到哪个GameObject上则由ManagerCreationProvider所提供的参数决定,如果没有这个名字的GameObject则会自动创建一个),当作一个单例:

注意到这个class必须是MonoBehaviour的派生类,且必须是非抽象类和非泛型类,否则没法挂载。

具体挂到CORE下的哪一个GameObject上则由ManagerCreationProvider里的ManagerType参数决定,比如ManagerType.UICore就会挂载到UICore下面,此参数只是提供一个分类方便查找,无实际作用,默认ManagerType=ManagerType.OtherCore。

此挂载具有覆盖作用:

比如,如果一个类GameSelection2继承了GameSelection,并且也有带有ManagerCreationProvider这个Attribute,那么单例GameSelection将会被GameSelection2替换。

此外,如果想快速创建一个单例类,可以继承ManagerBehaviour<T>,此父类提供了一个访问单例的instance字段(Field),但是注意不要在Awake或Start里访问此字段(Field),否则会报空引用。

如果想快速创建一个设计网络同步的单例类,可以继承NetworkManagerBehaviour<T>,功能与ManagerBehaviour<T>相差无几。

加载IManagerBehaviour

IManagerBehaviour同样继承了接口IInitializer。

在场景中所有继承了IManagerBehaviour的Component在这一阶段都会被初始化。

比如此示例:

https://github.com/VMware233/VMFramework/blob/main/Assets/Examples/Procedure/BasicManagerBehaviour.cs
using VMFramework.Procedure;

namespace VMFramework.Examples
{
    [ManagerCreationProvider("Demo")]
    public sealed class BasicManagerBehaviour : ManagerBehaviour<BasicManagerBehaviour>
    {
        protected override void OnBeforeInitStart()
        {
            base.OnBeforeInitStart();
            
            // Add any code here that needs to be executed to initialize the manager.
        }
    }
}

但是上面示例中的OnBeforeInitStart的调用顺序为InitializationOrder.OnBeforeInitStart,如果别的调用顺序,可以看下面例子:

https://github.com/VMware233/VMFramework/blob/main/Assets/Examples/Procedure/CustomInitializationManagerBehaviour.cs
using System;
using System.Collections.Generic;
using VMFramework.Core.Linq;
using VMFramework.Procedure;

namespace VMFramework.Examples
{
    [ManagerCreationProvider("Demo")]
    public sealed class CustomInitializationManagerBehaviour
        : ManagerBehaviour<CustomInitializationManagerBehaviour>
    {
        protected override void GetInitializationActions(ICollection<InitializationAction> actions)
        {
            base.GetInitializationActions(actions);
            
            actions.Add(new InitializationAction(InitializationOrder.InitComplete, OnInitComplete, this));
        }

        private void OnInitComplete(Action onDone)
        {
            // Write your initialization code here.

            onDone();
        }
    }
}

最后更新于

这有帮助吗?