base on ET framework(基于ET框架魔改的一个框架)
---框架尚在开发当中---
安装mongodb数据库,编译服务器并运行,打开Unity的Init场景并运行,即可登录游戏
- 调整程序集结构
- Scene流程拆分调整
- Unit拆分调整
- 消息调用接口生成
- 实体组件、属性自动同步
- 分离网络Session相关为单独程序集
- 接入PuerTs脚本方案(仅用于ui逻辑编写,核心玩法仍使用C#编写并基于HybridCLR热更方案)
- 接入Luban表格配置方案
- 接入EGamePlay技能系统
- 实现了一个简单的BundleFile资源管理系统
- 引入AOP面向切面编程流程
- 以及其他
AOGame将代码工程改回ET5那样的前后端分离的结构
服务端程序集没有大的改动,主要设定Game.Model为模型层,Game.Run为逻辑层,并单独拆分网络Session模块为Server.Outer程序集,这是为了让业务程序集专注于业务相关
客户端则去掉为了实现热重载额外添加的镜像程序集,转而通过将程序集切换到无效平台实现编辑器下的dll热重载
同样设定Game.Model为模型层,Game.Run为逻辑层,并单独拆分网络Session模块为Client.Outer程序集,另外设定Game.ViewCtrl为视图逻辑程序集
AOGame将ET的Scene拆分成App和Scene,App表示业务应用,App又进一步拆分成各个类型App,例如RealmApp、GateApp、MapApp等,Scene则单独表示场景Scene。
AOGame将ET的Unit拆分成Avatar、Npc和ItemUnit,Avatar表示玩家地图单位,Npc表示非玩家地图单位(怪物也属于Npc单位),ItemUnit表示其他非生命地图单位。
为什么要拆分Scene和Unit?实体的类型和类型实体的不同。
-
实体的类型即功能一样的用同一实体辅以字段区分不同类型,比如场景Scene或物品Item,包子和馒头就是功能一样的Item,都有着相同的字段,只是字段的值不一样,id和name的值不一样,物品的功能都一样所以用同一实体统一管理。
-
类型实体即功能有所差别的用不同类型实体辅以接口判断归类,比如App,MapApp和GateApp虽然都是IApp,但是他们的功能有非常大的差别,所以用类型实体流程分而治之。
从下图我们可以非常清晰明了的看到组成整个游戏服的所有类型App
- 前缀 b 表示base,基础服。
- 前缀 c 表示center,中心服,一个区只有一个。
- 前缀 g 表示global,全局服,整个分布式服务机制里只有一个。
- 前缀 s 表示serve,游戏的主要业务服。
走向不固定,可叠加的状态,可使用模式机制,比如ClientMode客户端模式
走向固定,互斥且不可叠加的状态,可使用流程WorkFlow,比如回合制的战斗流程,开始-进行-结束
CombatFlowLauncher
ToBranch
AOGame添加消息调用接口生成流程,通过生成AvatarCall类及方法去发送消息
客户端可以这样发送消息请求
var response = AvatarCall.C2M_SpellRequest(new C2M_SpellRequest() { CastPoint = hitPoint, SkillId = 1002 });
服务端可以这样推送消息给客户端
newAvatar.ClientCall.M2C_CreateMyUnit(new M2C_CreateMyUnit() { Unit = unitInfo });
-
当组件属性加上NotifySelf特性,属性的变化会自动同步给自己的客户端
-
当组件属性加上NotifyAOI特性,属性的变化会自动同步给AOI内的客户端,包括自己
-
当组件属性加上PropertyChanged特性,属性的变化会触发逻辑层的响应(仅客户端)
-
C#代码会如此响应(仅客户端):
- Ts代码会如此响应(仅客户端):
属性变化的同步和响应都是基于AOP面向切面编程实现的,可以减少许多重复的代码
下面是BundleFile资源管理系统主要的脚本
- ArtFilesConfig脚本收集资源打组并构建AssetBundle
- ArtFilesUpdater脚本更新下载版本资源
- Asset脚本加载资源