3.4事件机制EventSystem.md 4.5 KB

事件机制EventSystem

ECS最重要的特性一是数据跟逻辑分离,二是数据驱动逻辑。什么是数据驱动逻辑呢?不太好理解,我们举个例子 一个moba游戏,英雄都有血条,血条会在人物头上显示,也会在左上方头像UI上显示。这时候服务端发来一个扣血消息。我们怎么处理这个消息?第一种方法,在消息处理函数中修改英雄的血数值,修改头像上血条显示,同时修改头像UI的血条。这种方式很明显造成了模块间的耦合。第二种方法,扣血消息处理函数中只是改变血值,血值的改变抛出一个hpchange的事件,人物头像模块跟UI模块都订阅血值改变事件,在订阅的方法中分别处理自己的逻辑,这样各个模块负责自己的逻辑,没有耦合。 ET提供了多种事件,事件都是可以多次订阅的:

  1. AwakeSystem,组件工厂创建组件后抛出,只抛出一次,可以带参数

    Player player = ComponentFactory.Create<Player>();
    
    // 订阅Player的Awake事件
    public class PlayerAwakeSystem: AwakeSystem<Player>
    {
        public override void Awake(Player self)
        {
        }
    }
    
    1. StartSystem,组件UpdateSystem调用前抛出 csharp // 订阅Player的Start事件 public class PlayerStartSystem: StartSystem<Player> { public override void Start(Player self) { } }
  2. UpdateSystem,组件每帧抛出

    // 订阅Player的Update事件
    public class PlayerUpdateSystem: UpdateSystem<Player>
    {
        public override void Update(Player self)
        {
        }
    }
    
    1. DestroySystem,组件删除时抛出 ```csharp // 订阅Player的Destroy事件 public class PlayerDestroySystem: DestroySystem { public override void Destroy(Player self) { } }
    2. Player player = ComponentFactory.Create(); // 这里会触发Destroy事件 player.Dispose(); ```

    3. ChangeSystem,组件内容改变时抛出,需要开发者手动触发

      // 订阅Player的Destroy事件
      public class PlayerChangeSystem: ChangeSystem<Player>
      {
          public override void Change(Player self)
          {
          }
      }
      
      Player player = ComponentFactory.Create<Player>();
      // 需要手动触发ChangeSystem
      Game.EventSystem.Change(player);
      
      1. DeserializeSystem,组件反序列化之后抛出 ```csharp // 订阅Player的Deserialize事件 public class PlayerDeserializeSystem: DeserializeSystem { public override void Deserialize(Player self) { } }
      2. // 这里player2会触发Deserialize事件 Player player2 = MongoHelper.FromBson(player.ToBson()); ```

      3. LoadSystem,EventSystem加载dll时抛出,用于服务端热更新,重新加载dll做一些处理,比如重新注册handler

        // 订阅Player的Load事件
        public class PlayerLoadSystem: LoadSystem<Player>
        {
            public override void Load(Player self)
            {
            }
        }
        
        1. 普通的Event,由开发者自己抛出,可以最多带三个参数。另外客户端热更层也可以订阅mono层的Event事件 ```csharp int oldhp = 10; int newhp = 5; // 抛出hp改变事件 Game.EventSystem.Run("HpChange", oldhp, newhp);

        // UI订阅hp改变事件 [Event("HpChange")] public class HpChange_ShowUI: AEvent {

        public override void Run(int a, int b)
        {
            throw new NotImplementedException();
        }
        

        }

        // 模型头顶血条模块也订阅hp改变事件 [Event("HpChange")] public class HpChange_ModelHeadChange: AEvent {

        public override void Run(int a, int b)
        {
            throw new NotImplementedException();
        }
        

        } ```

      4. 除此之外还有很多事件,例如消息事件。消息事件使用MessageHandler来声明,可以带参数指定哪种服务器需要订阅。

        	[MessageHandler(AppType.Gate)]
        	public class C2G_LoginGateHandler : AMRpcHandler<C2G_LoginGate, G2C_LoginGate>
        	{
        		protected override void Run(Session session, C2G_LoginGate message, Action<G2C_LoginGate> reply)
        		{
        			G2C_LoginGate response = new G2C_LoginGate();
        			reply(response);
        		}
        	}
        

        更具体的消息事件等到讲消息的时候再细细讲解了

        1. 数值事件,数值模块再讲解
          ......, 更多的事件由自己去开发。

        ET框架的逻辑就是由以上各种事件来驱动的。