ET框架的基础逻辑,生命周期和Scene层级树

ET框架的基础逻辑

ECS思想和OOP思想的区别

​ 以传统RPG游戏为例,游戏中可能有Player,NPC,Monster等角色。传统的OOP思想主要是大量运用继承抽象多态,用来实现不同对象的需求。

​ 而ECS则是将所有对象设看作一个实体,所有功能都看作组件,不同功能的对象其实就是挂载了不同组件的实体。所有实体都是等价的,不会出现实体间继承的状况,这样可以很轻松的完成功能多样的不同实体,并增强组件的复用性。

ECS下简易的逻辑的分发

​ 仍用上述举例,介绍一下简单的逻辑分发过程。

  • Model

    Model层负责定义实体和组件,在这里要定义实体Unit,以及一些组件(MoveComponent,CombatComponent等)以及还需定义UnitType的枚举,以便后续逻辑的分发处理

    注意:

    Model下的实体不能调用UnityAPI,与Unity交互的组件实体只能放在ModelView下

    Model中只能存在数据,例如position,UnitType不能有对数据的操作

  • ModelView

    负责定义与Unity交互的实体和组件,有一些诸如动画组件,GameObject组件用到的数据由Unity提供,就需要将这些实体组件放到这个下面。

  • Hotfix

    Hotfix负责System行为的定义,提供创建实体和为实体挂载组件的功能。此时定义的UnitFactory工厂就应为不同的实体提供不同的创建方法,例如CreatePlayer,就应先将UnitType置为Player,为其添加MoveComponent组件等待操作。再如CreateNPC,UnitType设置为NPC后,由于npc一般不会移动则无需添加移动组件,可以添加对话组件等待。

    注意:

    Hotfix下只能定义行为,不能包含数据状态,只能对Model提供的数据状态进行相关操作

    Hotfix下也不能使用Unity Api 对于一些需要Unity才能挂载的组件,需要放到view中执行

  • HotfixView

    HotfixView负责需要与Unity交互的System行为,例如加载模型prefab,实例化游戏对象GameObject,若实体中需要用到GameObject对象,则还应为Unit实体添加GameObject组件,里面存有gameObject。若Unit实体还需要在场景中播放动画,还需要为其添加使用了UnityApi的AnimatorComponent。

    同理,在处理与Unity交互的System行为时,不同类型的Unit也可能行为有所不同,在此需要针对UnitType提供不同的行为。

ET框架下实体的生命周期

在Hotfix下编写实体生命周期的行为,创建相应的类实现特定生命周期接口即可,xxxSystem<>,注意对应实体需实现IAwake等接口

Computer.cs

namespace ET
{
    /// <summary>
    /// 实体:主机
    /// </summary>
    public class Computer:Entity,IAwake,IUpdate,IDestroy
    {

    }
}

ComputerSystem.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ET
{
    public class ComputerAwakeSystem:AwakeSystem<Computer>
    {
        public override void Awake(Computer self)
        {
            Log.Debug("ComputerAwake!!!!");
        }

        public class ComputerUpdateSystem : UpdateSystem<Computer>
        {
            public override void Update(Computer self)
            {
                Log.Debug("Computer Update !!!");
            }
        }

        public class ComputerDestroySystem:DestroySystem<Computer>
        {
            public override void Destroy(Computer self)
            {
                Log.Debug("Computer Destroy !!");
            }
        }

    }

    public static class ComputerSystem
    {
        public static void Start(this Computer self)
        {
            //启动前先开启电源
            self.GetComponent<PCCaseComponent>().StartPower();
            Log.Debug("Computer Start!!!!");
            //启动后开启显示器
            self.GetComponent<MonitorsComponent>().Display();
            
            
        }
    }
}

触发实体的Awake生命周期一般是用 xxxScene.AddChild<实体名>()进行触发,表示将一个实体添加到一个场景的子节点中,即实例化过程,返回的对象即为实例化对象。 可通过实体对象.Dispose()释放掉,触发Destroy生命周期

ET框架的Scene树

在ET框架下,Scene即为场景作为根节点,根节点下可以存放多个实体或组件。但Scenen本质也是实体,所以Scene之间也会有层次关系。

游戏客户端的Scene层次结构

在这里插入图片描述

  • GameScene

    游戏客户端全局的Scene根节点,用于提供游戏客户端全局且必要的基础功能组件(资源加载管理组件,计时器组件等)

  • ZoneScene

    用于提供玩家全局游戏业务功能逻辑组件(例如基础UI,背包界面等)

  • CurrentScene

    代表玩家当前所在的地图场景,一般用于挂载当前场景相关的组件,切换或释放场景时回收所有实体及组件。

游戏服务端Scene层次结构
在这里插入图片描述

  • GameScene

    ​ 类似客户端,其用来挂载全局服务端所需的基础功能必备组件

  • ZoneScene

    ​ 可以创建多个不同功能的ZoneScene, 每个不同功能的ZoneScene下挂载其应该具有的功能组件,例如网关下的NetKcpComponent,定位服务器的LocationComponent等等,一般通过SceneType的枚举对其进行逻辑分发。

    ​ 不同ZoneScene可以存在一个进程上面,也可以每个都ZoneScene运行在一个单独的进程上,不同ZoneScene进程甚至可以分布在服务器集群上,大大提高了运行效率。

    ​ Scene可以动态创建和销毁(用于制作副本等临时场景)

创建Scene的一般流程

  1. 创建一个未挂载任何组件的Scene对象 Scene scene = EntitySceneFactory.CreateScene(id, instanceId, zone, sceneType, name, parent);

  2. 添加服务器下Scene的公共组件mailBox(用于接收Actor消息),scene.AddComponent<MailBoxComponent, MailboxType>(MailboxType.UnOrderMessageDispatcher);

  3. 根据scene.SceneType针对不同服务器添加相应的组件,做相应的逻辑处理。

    switch (scene.SceneType)
    {
    	case SceneType.Realm:
    		scene.AddComponent<NetKcpComponent, IPEndPoint, int>(startSceneConfig.OuterIPPort, SessionStreamDispatcherType.SessionStreamDispatcherServerOuter);
    		break;
     	case SceneType.Gate:
            scene.AddComponent<NetKcpComponent, IPEndPoint, int>(startSceneConfig.OuterIPPort, SessionStreamDispatcherType.SessionStreamDispatcherServerOuter);
            scene.AddComponent<PlayerComponent>();
            scene.AddComponent<GateSessionKeyComponent>();
            break;
       	case SceneType.Map:
            scene.AddComponent<UnitComponent>();
            scene.AddComponent<AOIManagerComponent>();
            break;
        case SceneType.Location:
            scene.AddComponent<LocationComponent>();
            break;
    }
    

创建自定义场景的基本步骤

  1. 在SceneType枚举中添加自定义名称

  2. 在SceneFactory中添加自定义场景类型所应该处理的相关逻辑

  3. 在Excel配置表中添加自定义场景信息,并生成相应cs文件
    在这里插入图片描述

具体有关Excel的配置,笔者会在后续的博客中详细介绍

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值