- 安装.NetCore6.0
- 安装mongodb4.x
- 打开git clone本项目https://github.com/leeveel/GeekServer.git
- 运行Tools/ExcelGen/ExcelToCode.exe 点击[服务器-ALL]导出配置表
- 用VisualStudio2022打开GeekServer.sln 启动GeekServer.App
- 启动GeekServer.TestPressure (一个1000人登录的demo)
- 打开UnityDemo工程,打开SampleScene,运行查看日志(检查Main Camera上是否有脚本丢失,如果有请挂载GameMain.cs)
以demo为例,demo中有两个Actor(可以理解为逻辑上的线程),一个是Server,另外一个是Role,Server线程是全局的一个服务器只会存在一个,而Role则是一个玩家一个线程。在demo中Server线程负责了登录以及世界等级相关逻辑(实际开发中规划一个LoginActor比较合理),于是为Server注册了LoginComp和ServerComp两个组件。对于Role来说,一个玩家会存在很多功能系统,如角色模块,背包模块,宠物模块,所有为Role注册RoleComp,BagComp,PetComp。
也就是说一个功能系统的逻辑是运行在哪个线程上,取决于你把这个功能系统的组件注册在哪个Actor上。
通过Comp注解为Actor注册组件
[Comp(ActorType.Role)]
public class BagComp : StateComp
一个功能系统由两部分组成,1是逻辑代码(xxxCompAgent),2是数据(xxxState),为了实现逻辑代码的热更新,GeekServer使用了代理的方式将逻辑与数据分离。以下代码展示组件和数据的绑定方式:
[Comp(ActorType.Role)]
public class BagComp : StateComp
public class BagCompAgent : StateCompAgent<BagComp, BagState>
请参见Geek.Server.Role.PetCompAgent
请参见Server.Logic.Logic.ServerCompAgent
请参见Server.Logic.Logic.ServerCompAgent.GetWorldLevel()接口,此接口是获取服务器世界等级,由于这个接口会对外部提供服务,即其他Actor都有可能访它,所以需要添加[Api]注解
[Api]:代表此接口需要被其他Actor调用
[Discard]:代表在调用此接口的时候,会使用弃元运算符(_ = DoSomething()),因为弃元运算符会导致执行此异步函数逻辑的线程不可确定,所以GeekServer对标记了[Discard]注解的处理方式是,强制插入队列末端执行。
[ThreadSafe]:代表此接口是线程安全的,不是必须的,而且应该尽量少用(1.让逻辑开发人员尽量少关注多线程 2.如果标注的接口逻辑很复杂,再代码多次迭代之后,很容易误判)
[TimeOut(30000)]:可以自定义接口的超时时间
具体代码请参见Server.Logic.Logic.ServerCompAgent
在demo中可以看到客户端的ReqXXX消息,在服务器回包当中,都带上了ReqXXX传过来的Unid。demo中这个设计为了解决自动处理客户端(发送消息->锁屏->收到回包->解锁屏)的逻辑。如果你有自己的方案或者不需要此设计忽略它。