Unity3dC#分布式游戏服务器ET框架介绍-组件式设计
前⼏天写了,受到很多⼈关注,QQ⼏天就加了80多个⼈。开源这个框架的主要⽬的也是分享⾃⼰设计ET的⼀些想法,所以我准备写⼀系列的⽂章,介绍下⾃⼰的思路跟设
计,每篇⼀个主题,这次介绍的是组件设计。
在代码复⽤和组织数据⽅⾯,⾯向对象可能是⼤家第⼀反应。⾯向对象三⼤特性继承,封装,多态,在⼀定程度上能解决不少代码复⽤,数据复⽤的问题。不过⾯向对象不是万
能的,它也有极⼤的缺陷:
1. 数据结构耦合性极强
⼀旦⽗类中增加或删除某个字段,可能要影响到所有⼦类,影响到所有⼦类相关的逻辑。这显得⾮常不灵活,在⼀套复杂的继承体系中,往⽗类中改变字段会变得越来越⿇烦,⽐⽅说ABC是D的⼦类,某天发现需要增加⼀个AB都有的数据,但是C没2. 难以热插拔
好看页面table样式继承结构⽆法运⾏时增加删除字段,⽐如玩家Player平常是⾛路,使⽤坐骑后就骑马。问题是坐骑的相关信息就需要⼀直挂在Player对象上⾯。这就显得很不灵活,我不骑马的时候内存中为啥要有马的数据?接⼝也有同样的问题,⼀个类实现了⼀个接
使⽤⾯向对象可能导致灾难性后果,游戏开发中有新⼈有⽼⼈,有技术好的,有技术差的。⼈都是喜欢偷懒的,当你发现调整继承关系⿇烦的时候,有可能AB中增加⼀个字段为
了省事直接就放到⽗类D中去了。导致C莫名奇妙的多了⼀个⽆⽤的字段。关键还没法发现,最后导致⽗类D越来越⼤,到最后有可能⼲脆就不⽤ABC了,直接让所有对象都变成
D,⽅便嘛!是的,很多游戏就是这么⼲的,开发到最后根本就不管继承关系了,因为想管也管不了了。
⾯向对象在⾯对复杂的游戏逻辑时很⽆⼒,所以很多游戏开发者⼜倒退了回去,使⽤⾯向过程进⾏开发游戏,⾯向过程,简单粗暴,不考虑复杂的继承,不考虑抽象,不考虑多
态,是开发届的freestyle,挽起袖⼦就开撸,但同时,代码逻辑的复⽤性,数据的复⽤性也⼤⼤降低。⾯向过程也不是⼀种好的游戏开发模式。
组件模式很好的解决了⾯向对象以及⾯向过程的种种缺陷,在游戏客户端中使⽤⾮常⼴泛,Unity3d,虚幻4,等等都使⽤了组件模式。组件模式的特点:
1.⾼度模块化,⼀个组件就是⼀份数据加⼀段逻辑
2.组件可热插拔,需要就加上,不需要就删除
3.类型之间依赖极少,任何类型增加或删除组件不会影响到其它类型。
但是⽬前只有极少有服务端使⽤了组件的设计,守望先锋服务端应该是使⽤了组件的设计,守望先锋的开发⼈员称之为ECS架构,其实就是组件模式的⼀个变种,E就是
Entity,C就是Component,S是System,其实就是将组件Component的逻辑与数据剥离,逻辑部分叫System,话题扯远了,还是回到ET框架来把。
ET框架使⽤了组件的设计。⼀切都是Entity和Component,任何类继承于Entity都可以挂载组件,例如玩家类:
public sealed class Player : Entity
{
public string Account { get; private set; }
public long UnitId { get; set; }
public void Awake(string account)
{
this.Account = account;
}
public override void Dispose()
{
if (this.Id == 0)游戏辅助框架免root
{
return;
}
base.Dispose();
}
}
font weight bold属性能够设置文本加粗给玩家对象挂载个移动组件MoveComponent,这样玩家就可以移动了,给玩家挂上⼀个背包组件,玩家就可以管理物品了,给玩家挂上技能组件,那么玩家就可以施放技能
了,加上Buff组件就可以管理buff了。
player.AddComponent<MoveComponent>();
player.AddComponent<ItemsComponent>();
player.AddComponent<SpellComponent>();
player.AddComponent<BuffComponent>();
组件是⾼度可以复⽤的,⽐如⼀个NPC,他也可以移动,给NPC也挂上MoveComponent就⾏了,有的NPC也可以施放技能,那么给它挂上SpellComponent,NPC不需要背
包,那么就不⽤挂ItemsComponent了
ET框架模块全部做成了组件的形式,⼀个进程也是由不同的组件拼接⽽成。⽐⽅说Loginserver需要对
外连接也需要与服务器内部进⾏连接,那么login server挂上
// 内⽹⽹络组件NetInnerComponent,处理对内⽹连接
Game.Scene.AddComponent<NetInnerComponent, string, int>(innerConfig.Host, innerConfig.Port);
// 外⽹⽹络组件NetOuterComponent,处理与客户端连接
Game.Scene.AddComponent<NetOuterComponent, string, int>(outerConfig.Host, outerConfig.Port);
⽐如battle server就不需要对外⽹连接(外⽹消息由gateserver转发),那么很⾃然的只需要挂载⼀个内⽹组件即可。
类似Unity3d的组件,ET框架也提供了组件事件,例如Awake,Start,Update等。要给⼀个Component或者Entity加上这些事件,必须写⼀个辅助类。⽐如NetInnerComponent
组件需要Awake跟Update⽅法,那么添加⼀个这样的类即可:
[ObjectEvent]
public class NetInnerComponentEvent : ObjectEvent<NetInnerComponent>, IAwake, IUpdate
{
public void Awake()
{
this.Get().Awake();
抽屉导轨}
transmitt什么意思public void Update()
{
this.Get().Update();
}
}
这样,NetInnerComponent在AddComponent之后会调⽤其Awake⽅法,并且每帧调⽤Update⽅法。
ET没有像Unity使⽤反射去实现这种功能,因为反射性能⽐较差,⽽且这样实现的好处是这个类可以放到热更dll中,这样组件的Awake Start,Update⽅法以及其它⽅法都可以放
header是什么元件一引脚到热更层中。将Entity和Component做成没有⽅法的类,⽅法都放到热更层,⽅便热更修复逻辑bug。
组件式开发最⼤的好处就是不管菜鸟还是⾼⼿,开发⼀个功能都能很快的知道怎么组织数据怎么组织逻辑。可以完全放弃⾯向对象。使⽤⾯向对象开发最头疼的就是我该继承哪
个类呢?之前做过最恐怖的就是虚幻三,虚幻三的继承结构⾮常多层,完全不知道⾃⼰需要从哪⾥开始继承。最后可能导致⼀个⾮常⼩的功能,继承了⼀个及其巨⼤的类,这在
虚幻三开发中屡见不鲜。所以虚幻4改⽤了组件模式。组件模式的模块隔离性⾮常好,技术菜鸟某个组件写得⾮常差,也不会影响到其它模块,⼤不了重写这个组件就好了。
正是因为ET使⽤了可拆卸的组件模式,ET可以将所有服务器组件都装到同⼀个进程上,那么这⼀个进程就可以当作⼀组分布式服务器使⽤。从此⽤vs调试分布式服务器成为了
可能。正因为这样,平常开发只使⽤⼀个进程,发布的时候发布成多个进程就⾏了。说实在的,不是吹⽜,这是⼀个伟⼤的发明,这⼀发明解决了分布式游戏服务器开发中的⼤
⼤⼤难题,极⼤的提⾼了开发效率。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论