提交 e59bbc17 编写于 作者: T tanghai

加上英文翻译

上级 9b5d6840
# component design
In terms of code reuse and organization data, object oriented is probably the first response. The three characteristics of object-oriented inheritance, encapsulation, polymorphism, to a certain extent, can solve a lot of code reuse, data reuse problems. However, object oriented is not omnipotent, it also has great defects:
### 1. the data organization and strong coupling
Once a field is added or deleted in the parent class, all subclasses may be affected, affecting all subclasses related logic. This is not very flexible, in a complex inheritance system, to change the parent class field will become more and more trouble, for example, ABC is a subclass of D, one day found a need to increase the AB of some data, but not C, then this data is certainly not good in a parent class, can only be AB abstract a parent class E inherited from D, E, AB were added to E in some fields, once the inheritance structure changes, may also need to change the interface, for example, before a interface into the parameter type is E, when the AB is not in the field need to be shared, so need to adjust the inheritance relationship, let AB inherited from D, so this interface requires the parameter type logic code into D, which are likely to adjust. Even more frightening is that the game logic changes are very complex, very frequent, may add a field today, and tomorrow deleted, and if each time to adjust the inheritance structure, this is simply a nightmare. Inheritance structure is very weak in the face of frequent data structure adjustment. There is also a serious problem that the inheritance structure can not be run, add delete fields, such as the player Player usually walk, after riding the horse riding. The problem is that the mount's relevant information needs to hang on top of the Player object. This is very inflexible. Why do I have horse data in my memory when I'm not riding?
### 2. interface logic is difficult to reuse, hot swap.
The object oriented method of processing the same behavior is to inherit the same parent class or interface. The problem is that the interface does not implement the code, but it needs its subclass to write its own implementation. Obviously, the same function, each subclass can write a similar code. This makes the code for the interface not reusable. There is a problem, a class implements an interface, so the interface will stick to this kind of person, you want to get rid of her not to ride, or as an example, game player Player can ride, then may inherit a riding interface, the problem is, when I Player from the mounts down, Player game player who still has a riding interface, can't delete this dynamic interface! The possible examples are not quite right, but the arguments should be clear.
### 3. the use of object-oriented could lead to disastrous consequences
There are new people in the game development, old people, good technology, poor technology. People are lazy, when you find the adjustment inheritance relationship trouble, it is possible to add a field in AB, in order to save, directly into the parent class D to go. C leads to a much more useless field. The key can not be found, and finally led to the father class D more and more big, and finally may simply do not use ABC, directly make all objects become D, convenient! Yes, a lot of games do that, and at the end of the development, they don't care about inheritance, because they don't want to manage it.
Object oriented is weak in the face of complex game logic, so many game developers had retreated back, using the process oriented development game, process oriented, simple and rough, without considering the complex inheritance, is not considered abstract, without considering the polymorphism, is the development of the freestyle, roll up their sleeves and open up, but at the same time the logic, code reuse, reuse of data is greatly reduced. Process oriented is not a good game development model, either.
Component mode solves the defects of object oriented and process oriented, which is widely used in game client, Unity3d, unreal 4, and so on. Features of component patterns:
1. highly modular, a component is a data plus a section of logic
2. components can be hot plug, need to add, not need to delete
There is very little dependency between 3. types, and any type of addition or deletion of components does not affect other types.
At present, only a few have the server to use components design, the server should watch pioneer is the use of component design, and the pioneer developer called ECS architecture, in fact is a variant of component model, E is Entity, C is Component, S is System, which is the logic and data stripping assembly Component the logic part is called System, the topic Cheyuan, or to return to the ET framework.
The ET framework uses the design of components. Everything is Entity and Component, and any object that inherits from Entity can mount components, such as player objects:
```C#
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)
{
return;
}
base.Dispose();
}
}
```
.
To mount a MoveComponent mobile game player object component, so you can move the game player, game player to hang a backpack assembly, game player can manage the goods, to hang up the game player skill components, then you can spell the game player, plus the Buff component can manage buff.
```C#
player.AddComponent<MoveComponent>();
player.AddComponent<ItemsComponent>();
player.AddComponent<SpellComponent>();
player.AddComponent<BuffComponent>();
```
Component is highly reusable, such as a NPC, he can move to NPC MoveComponent hanging on the line, some NPC can also cast skills, then give it to hang SpellComponent, NPC does not require a backpack, then do not hang ItemsComponent
ET framework modules are all made up of components, and a process is made up of different components. For example, Loginserver needs external connections and also needs to be connected to the server, so login server hangs on
```C#
// Internal network component NetInnerComponent, processing the internal network connection
Game.Scene.AddComponent<NetInnerComponent, string, int>(innerConfig.Host, innerConfig.Port);
// External network component NetOuterComponent, processing and client connection
Game.Scene.AddComponent<NetOuterComponent, string, int>(outerConfig.Host, outerConfig.Port);
```
For example, battle server does not need external network connection (external network message is forwarded by gateserver), so it is natural to install only one intranet component.
```C#
// Internal network component NetInnerComponent processing for internal network connection
Game.Scene.AddComponent<NetInnerComponent, string, int>(innerConfig.Host, innerConfig.Port);
```
Like Unity3d components, the ET framework also provides component events, such as Awake, Start, Update, and so on. To add these events to a Component or Entity, you must write a helper class. For example, NetInnerComponent components require Awake and Update methods, and then add a class like this:
```C#
[ObjectEvent]
public class NetInnerComponentEvent : ObjectEvent<NetInnerComponent>, IAwake, IUpdate
{
public void Awake()
{
this.Get().Awake();
}
public void Update()
{
this.Get().Update();
}
}
```
In this way, NetInnerComponent calls its Awake method after AddComponent, and calls the Update method per frame.
ET did not like Unity use reflection to achieve this function, the reflection performance is poor, and thus realize the benefits of this class can be more on the hot DLL, this component of the Awake Start, Update method and other methods are more on the hot layer. Only the data is placed on the model layer to facilitate the heat to repair the logical bug.
The biggest advantage of component development is that, regardless of the novice or master, the development of a function can quickly know how to organize data, how to organize logic. Object can be completely abandoned. The most difficult thing to use object-oriented development is what class should I inherit? The most frightening thing ever was illusion three, and the inheritance structure of unreal three was very multi-layered, and did not know where to begin. In the end, it may lead to a very small function, inheriting one and its huge class, which is common in unreal three development. So unreal 4 uses component mode. The module isolation of component mode is very good. A component of the technical novice writes very badly, and it doesn't affect other modules, so it is impossible to rewrite this component.
The design of # network layer
The ET framework provides a more powerful network messaging layer, sending messages, subscribing to messages, and making it easy, very clear and simple.
#### 1. send common message
There are two main components, NetOuterComponent handles the connection of the client, and NetInnerComponent handles the connection within the server
The two components can access the connection according to the address, each connection is encapsulated into a Session object, and the Session object has two methods for sending the message:
``` C#
// Create or access a connection according to the address
Session session = Game.Scene.GetComponent<NetInnerComponent>().Get(innerAddress);
// Send only and no return
session.Send(new R2G_GetLoginKey());
// Send the R2G_GetLoginKey message and wait for the message to return a G2R_GetLoginKey message
G2R_GetLoginKey g2RGetLoginKey = await session.Call<G2R_GetLoginKey>(new R2G_GetLoginKey() {Account = "zhangsan"});
Log.Debug("print response message content: " + g2RGetLoginKey.ToJson())
```
Because of C#'s powerful async await syntax, ET framework RPC message is very simple, after sending logic to be coherent, without dismantling the two logic, because of this characteristic, C# distributed framework for writing very much, because it is nothing more than a distributed inter process network news. If you don't have this function, think about it, send the message in one place, you have to subscribe to a return message, and the two piece of code is disconnected. Even more frightening is the continuous multiple RPC requests:
``` C#
// The client sends an account password to the login server to verify, and waits for the login response message to return, login will assign a gateway to the client
R2C_Login r2CLogin = await session.Call<R2C_Login>(new C2R_Login() { Account = "a", Password = "b" });
// Client connect gateway
Session gateSession = Game.Scene.GetComponent<NetOuterComponent>().Create(r2CLogin.Address);
// The client sends the message to the gateway and waits for the gateway to verify the return
G2C_LoginGate g2CLoginGate = await gateSession.Call<G2C_LoginGate>(new C2G_LoginGate(r2CLogin.Key));
Log.Info("login ok!");
// 获取玩家的物品信息
G2C_Items items = await gateSession.Call<G2C_Items>(new C2G_Items());
```
You can see the login LoginServer, immediately log on gateserver, after the completion of the query and login the game player items of information, the whole process looks very coherent, if there is no async await, this code will be split into at least 4 pieces in 4 functions. Distributed servers have many RPC calls, and there is no syntax support for async await, which is inconceivable. So some people use nodejs, java to write game server, I can not understand, write a single clothing can also, write distributed server, ha ha!
#### 2. ordinary news subscription
The top is sending messages. How does the server subscribe to processing a message? Very concise:
```C#
// Processing login RPC messages and returning response
[MessageHandler(AppType.Login)]
public class C2R_LoginHandler : AMRpcHandler<C2R_Login, R2C_Login>
{
protected override async void Run(Session session, C2R_Login message, Action<R2C_Login> reply)
{
R2C_Login response = new R2C_Login();
try
{
Log.Debug(message.ToJson());
reply(response);
}
catch (Exception e)
{
ReplyError(response, e, reply);
}
}
}
```
RPC message only need to add a hotfix class in DLL class, inherited from AMRpcHandler, virtual method, ET uses a declarative message subscription approach, a RPC message processing class, only need to add the MessageHandlerAttribute can automatically be found and registered to the frame frame, does not need to register with manual function. The class MessageHandlerAttribute above sets the AppType.Login, which indicates that only the Login server registers the RPC processing class. Is it very simple? Similarly, registering non RPC messages only needs to add a class that inherits from AMHandler. The entire message handling class does not contain any state, so it can be reload.
#### 3. send actor message
The ET framework also provides a distributed message mechanism similar to the Erlang language, regardless of any object in the process, only the ActorComponent mount components need, any process can take the object of ID, sending the object message, messages are sent to the object in the process and to the object processing. Sending Actor messages is different from ordinary messages. To send actor messages, server must hang on the ActorProxyComponent components:
```c#
// ActorProxyComponent get actorproxy
ActorProxy actorProxy = Game.Scene.GetComponent<ActorProxyComponent>().Get(id);
// Sending messages to actor
actorProxy.Send(new Actor_Test());
// Sending rpc messages to actor
ActorRpc_TestResponse response = await actorProxy.Call<ActorRpc_TestResponse>(ActorRpc_TestRequest());
```
#### 4.actor subscription processing
Subscribing to actor messages is just like regular messages, just inheriting AMActorHandler and adding ActorMessageHandler tags. The difference is that AMActorHandler needs to provide the type of Actor, such as the following actor message, which is sent to the Player object
```c#
[ActorMessageHandler(AppType.Map)]
public class Actor_TestHandler : AMActorHandler<Player, Actor_Test>
{
protected override async Task<bool> Run(Player player, Actor_Test message)
{
Log.Debug(message.Info);
player.GetComponent<UnitGateComponent>().GetActorProxy().Send(message);
return true;
}
}
```
Similarly, subscribing to ActorRpc messages requires inheritance of AMActorRpcHandler, and also using reply to return response messages.
```c#
[ActorMessageHandler(AppType.Map)]
public class ActorRpc_TestRequestHandler : AMActorRpcHandler<Player, ActorRpc_TestRequest, ActorRpc_TestResponse>
{
protected override async Task<bool> Run(Player entity, ActorRpc_TestRequest message, Action<ActorRpc_TestResponse> reply)
{
reply(new ActorRpc_TestResponse() {response = "response actor rpc"});
return true;
}
}
```
#### 5.Exception handling rpc message
ET framework message layer provides a powerful exception handling mechanism, all RPC response messages are inherited with AResponse, AResponse with error and error information,
```
public abstract class AResponse: AMessage
{
public uint RpcId;
public int Error = 0;
public string Message = "";
}
```
You can catch RpcException exceptions and do different exception handling through ErrorCode, such as client login:
```
try
{
R2C_Login r2CLogin = await session.Call<R2C_Login>(new C2R_Login() { Account = "a", Password = "b" });
}
catch (RpcException e)
{
if (e.Error == ErrorCode.ERR_AccountNotFound)
{
Log.Debug("account not exist");
return;
}
if (e.Error == ErrorCode.PasswordError;)
{
Log.Debug("password error");
return;
}
}
```
The ET framework is the most convenient anomaly information will cross process transfer, for example, the A process to the B process launched a Rpc request, B process needs to request C in response to C request response process before D, before the B results, the D process in the process of occurrence of an exception, the exception will from D- >C->B->A. The A process in try catch to capture the exception, the exception will BCD with the whole process of the stack information, check distributed abnormal bug becomes very simple.
#### summary
This paper introduces the network layer usage of ET framework, and the ET framework provides a very perfect distributed network layer, a powerful distributed exception handling mechanism. Because of the use of collaboration, ET send messages and remote call and its simple and convenient, distributed development is as convenient as the development of stand-alone.
##### 1.visual studio must use vs2017, other versions do not support VS2017, need to check the installation of the following contents:
.net desktop development
Using C++ desktop development, VC++ 2017 v141 toolset, XP support for C++
Visual studio tools for unity.Netcore2.0
##### must install unity 2017.1.0p5 2. unity to 2017.1.2, the other version is not supported
3. ##### start menu File->open project->open unity2017, select the Egametang/Unity folder, click to select the folder button.
4. click the Unity menu Assets->open ##### C# project vs compiler (compiler must start, right-click the VS solution, all the compiler)
5. ##### opened with vs2017 Egametang/Server/Server.sln compiler (must be compiled, right-click the VS solution, all the compiler)
##### 6. Unity->tools menu - > command line configuration, select the LocalAllServer.txt which is the start of a single App, if you want to start a group of multi App server, select 127.0.0.1.txt in the command line tool, click start, the specific configuration can they use the command-line utility to modify
##### 7. click Tools in the start, this will start the server (you can also use VS to start, convenient debugging step)
##### 8. running Unity, enter the account, then click on the login log connection Gate success, said OK!
## frame synchronization test
##### 1. Unity->tools menu - > package ->PC package, hit a PC package in the Release directory
##### 2. run Unity login into the hall into the scene
##### 3. run PC package login into the hall then there will be two people (overlap)
##### 4. click the right mouse button to move characters
# note:
The 15.4 version of VS2017 bug, Hotfix Assembly-CSharp.dll will prompt can not find, you need to Hotfix project Unity quoted with Unity.Plugin removed, directly referenced in the Unity\Library\ScriptAssemblies directory with Assembly-CSharp.dll Assembly-CSharp-firstpass.dll two DLL
The general reason for error is 1. not compiled. 2. Chinese catalogue. 3.vs does not install vs tools or is not the latest vs tools. 4. not installing.Netcore2.0
\ No newline at end of file
__chinese QQ group : 474643097__
### 1.A distributed server, can use visual studio debugging,N->1
Generally speaking, distributed server starts a lot of processes, once the process is more, single step debugging becomes very difficult, leading to server development basically rely on log to find the problem. Common development has opened a lot of game logic process, not only the slow start, and find the problem and not convenient to log pile check problem in a pile, this feeling is very bad, so many years no one can solve the problem. The ET framework uses a component design similar to the watch pioneer, and all server contents are disassembled into components, and the components that need to be mounted according to the type of server are started. It is a bit like a computer, the computer module is split into memory, CPU, motherboard parts and so on, collocation of different parts can be assembled into a different computer, such as home desktop CPU, motherboard, memory, graphics, display, hard disk. And the company uses the server does not need the display and graphics card, the Internet bar computer may not need hard disk, etc.. Because of this design, the ET framework can be all server components are linked in a server process, the server process has all the functions of the server, a process can be used as a whole set of distributed servers. It's also like a computer, which has all the computer components, and it can be used as a company server or as an Internet cafe.
### 2.A Distributed server, can freely split function,1->N
Distributed server to develop various types of server processes, such as Login server, gate server, battle server, chat server friend server, a server, the traditional development mode need to know in advance the function which should be put in the server, when more and more functions, such as chat on a central server then, need to split out into a separate server, this will involve a large number of code migration work, tired. The ET framework does not really need to be concerned about what kind of functionality the current development will place on server, and only uses one process to develop it, and the function is developed into a component. Is it convenient to use a multi process configuration to publish it into multiple processes when you publish it? How do you split the server?. You can split it with very few code changes. Different server hangs different components on it?!
### 3.Cross platform distributed server
ET framework uses C# as server-side, and now C# is completely cross platform, install.Netcore on Linux, you can do without modifying any code, you can run. Performance, now.Netcore performance is very strong, faster than Lua, python, JS faster. The game server completely be nothing difficult. We usually use VS to develop debugging on windows, and release it to Linux on the time of release. ET framework also provides a key synchronization tool, open unity->tools->rsync synchronization, you can synchronize the code to the linux
```bash
./Run.sh Config/StartConfig/192.168.12.188.txt
```
You can compile and start the server.
### 4.Provide Coroutine support
C# naturally supports asynchronous variable synchronous syntax async and await, much more powerful than Lua and python, and the new version of Python and JavaScript language even copy the C#'s co - operation grammar. There is no asynchronous syntax to support remote calls between distributed servers and a large number of servers, and development will be very troublesome. So Java does not have asynchronous syntax, doing single service is OK, not suitable for large-scale distributed game server. For example:
```c#
// Send C2R_Ping and wait for response message R2C_Ping
R2C_Ping pong = await session.Call<R2C_Ping>(new C2R_Ping());
Log.Debug("recv R2C_Ping");
// Query mongodb for a ID of 1 Player and wait for return
Player player = await Game.Scene.GetComponent<DBProxyComponent>().Query<Player>(1);
Log.Debug($"print player name: {player.Name}")
```
It can be seen that with async await, asynchronous operations between all servers will become very coherent, without disassembling into multiple sections of logic. Greatly simplifies the development of distributed servers
### 5.Provide actor message mechanism similar to Erlang
One of the advantages of Erlang language is the location transparent message mechanism. The user does not care about which process the object is in, and when you get the ID, you can send the message to the object. The ET framework also provides a actor message mechanism, the entity object need only hang ActorComponent components, the object becomes a Actor, any server only needs to know the object ID can send a message to it, totally do not care about this entity in which server, in which physical machine. This principle is actually very simple, the ET framework provides a location server, all mounted ActorComoponet object will own ID with location registration to the location server, the other server when sending the message object if you don't know the real position of the object, will go to the location server query, query to the position to be transmitted.
### 6.Provide server with dynamic update logic function
hotfix is an indispensable component of game server function, design using the ET framework, the design can be made to watch the pioneer, only component members, no way, all the way into an expansion method in hotfix DLL, when reload DLL can reload all logic more hot.
### 7.Client can hotfix
Because of the IOS restrictions, the previous unity hot update generally use Lua, leading to unity3d developers to write two kinds of code, trouble to death. Fortunately, the ILRuntime library comes out, using the ILRuntime library, unity3d can use the C# language to load the hot update DLL for thermal update. One drawback of ILRuntime is that it doesn't support VS debug at development time, which is a little uncomfortable. The ET framework uses a pre compiled instruction ILRuntime to seamlessly switch. ILRuntime is not used when developing, but using Assembly.Load to load the hot update dynamic library, so that it can be easily used VS single step debugging. At the time of release, defining the precompiled instruction ILRuntime can seamlessly switch to using ILRuntime to load the hot update dynamic library. So it's easy to develop and convenient
### 8.The client server uses the same language and shares the code
Download the ET framework, open the server project, you can see that the server referenced a lot of client code, through the client code approach to achieve a double end shared code. For example, the network message between the client and server can share a file on both sides, adding a message only needs to be modified.
### 9.Seamless handover of UDP TCP protocol
The ET framework not only supports TCP, but also support the reliable UDP protocol, UDP support is a package of ENet library, using the ENet and hero alliance network library, its characteristic is rapid, and the performance of the network packet loss situation is also very good, that we tested TCP in packet loss 5%, MoBa game card no, but the use of ENet, 20% packet loss still don't feel a card. Very powerful.
10 ### there are many, I will not detail
A. and its easy to check CPU occupancy and memory leak check, vs comes with analytical tools, no longer worry about performance and memory leak check
B. uses NLog library, hits log and its convenience, when develops normally, may hit all the server log to a document, also does not need each document search log again
C. unified the use of Mongodb bson serialization, the message and configuration files are all bson or JSON, and later use mongodb to do the database, and no longer need to format conversion.
D. provides a powerful AI behavior tree tool
E. provides a synchronization tool
F. provides command line configuration tools, configuring the distribution is very simple
The server side of the ET framework is a powerful and flexible distributed server architecture, which can fully meet the needs of most large games. Using this framework, the client developer can complete the double end development by himself, save a lot of manpower and material resources, and save a lot of communication time.
Usage method:
[start-guide](https://github.com/egametang/Egametang/blob/master/Doc/%E8%BF%90%E8%A1%8C%E6%8C%87%E5%8D%97.md)
[component-design](https://github.com/egametang/Egametang/blob/master/Doc/%E7%BB%84%E4%BB%B6%E8%AE%BE%E8%AE%A1.md)
[network-design](https://github.com/egametang/Egametang/blob/master/Doc/%E7%BD%91%E7%BB%9C%E5%B1%82%E8%AE%BE%E8%AE%A1.md)
__chinese QQ group: 474643097__
email: egametang@qq.com
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册