asksim
明白,ECS中对于此类场景有多重实现方案,咱们主要是讨论讨论此类场景中的最佳实践。讨论讨论高效、好用的方案。
我说说我的几种尝试,大家品品看看优劣。
第一种:
给组件挂上 MailBoxComponent ,使用 ActorMessageSenderComponent.Instance.Send(InstanceId, msg),发送消息给组件,组件接收消息自行处理。
1、这个方案需要在 proto 中添加协议
2、仅仅是一个函数调用,发送消息显得太重量级,不够高效。
3、处理多个相同的 Handler 比如下列情况
[ActorMessageHandler(SceneType.Game)]
public class HandlerA : AMActorHandler<AComponent, Msg>
{
protected override async ETTask Run(AComponent A, Msg message)
{
……
}
}
[ActorMessageHandler(SceneType.Game)]
public class HandlerA : AMActorHandler<BComponent, Msg>
{
protected override async ETTask Run(BComponent A, Msg message)
{
……
}
}
此时使用 ActorMessageSenderComponent.Instance.Send(InstanceId, msg) 发送消息,会给两个handler都发送,但如果 InstanceId 是A组件,那么在BHandler中会报类型转换失败,诚然可以用 SceneType 来区分,但场景设计中 逻辑上 domainScene 都是 Game 。由此,我认为该场景不适合此种解决方案。
第二种:
if (entity is AComponent comp)
{
comp.StartGame();
}else if(entity is BComponent comp)
{
comp.StartGame();
}
这种也是笔记里有写的一种方案

效率也高,但就是太丑了。多了会变成 if 海。
第三种:参考 字母哥 EUI 里的 IAUIEventHandler 接口
写一个 IGameEventHandler
public interface IGameEventHandler
{
void OnStartGame(GameDesk gameDesk);
}
public class AComponentHandler : IGameEventHandler
{
public void OnStartGame(Component gameDesk)
{
gameDesk.GetComponent<AComponent>().StartGame();
}
}
此时 使用 接口即可

这种方案其实是 switch case 的 OOP 升级版,效率高。目前我是用这个方案。但其实这个用的还是 OOP 思想。总觉得 ECS 的血统不纯正,哈哈哈。