系统框架设计优化

STAR

针对客户端新旧系统的快速迭代上线,负责在ILRuntime和uLua实现了热更业务系统框架搭建和设计,确保了游戏内容快速稳定更新迭代

配套工具链,自动生成代码模板,辅助工具,细分需求,让开发者聚焦核心业务,让整个工程风格统一,便于多人协作

Model-View-Controller(MVC)模式

Model-View-Controller pattern(MVC)模式将软件分成三个主要模块:Models (数据CRUD), Views (界面/事件检测)和Controllers (决策/处理).MVC实现起来足够灵活,即使是建立在ECS或OOP之上.

ECS: 要解决的最复杂、最核心的问题,或许还是网络同步。我认为这也是设计一个状态和行为严格分离的框架的主要动机。因为一个好的网络同步系统必须实现预测,有预测就有预测失败的情况,发生后要解决冲突,回滚状态是必须支持的。而状态回滚还包括了只回滚部分状态,而不能简单回滚整个世界。

好的框架可以统一多个开发人员的编程风格,方便多人协作

最重要的是可以大大的提高开发效率,大部分时间专心写业务就可以了

基础设计

MVC (只有MV)

M:Model,Operation

V:View

C:Plugin

PluginManager 注册Plugin,负责管理和创建Plugin,

Plugin:配置和UI的加载,Model 和 Operation的创建,

通信:Plugin之间通信,PluginManager.SendMessage(“PluginName”, “MessageType”,”Args”), 具体实现获取xxxPlugin,获取xxxOperation,反射调用指定attribute的方法,从而实现对抽象的依赖

Operation : 注册协议监听

系统资源的管理和加载

优化:当多个plugin打开后,用队列缓存起来,当打开的plugin超过三个后,卸载第一个plugin,减轻游戏运行时内存。

简易实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
class Program
{
static void Main()
{
KHPluginManager.Instance.Init();
KHPluginManager.Instance.SendMessage("UIPlugin", "OpenMainView");
}
}

class KHPluginManager
{
private static KHPluginManager? _instance;

public static KHPluginManager Instance
{
get
{
if (_instance == null)
{
_instance = new KHPluginManager();
}
return _instance;
}
}

public Dictionary<string, Plugin> plugins = new Dictionary<string, Plugin>();
public void Init()
{
plugins.Clear();
RegisterPlugin("UIPlugin", typeof(UIPlugin));
RegisterPlugin("GamePlugin", typeof(GamePlugin));
}

public void AddPlugin(Plugin plugin)
{
plugins.Add(plugin.name, plugin);
}

public Dictionary<string, Type> totalPlugin = new Dictionary<string, Type>();
public void RegisterPlugin(string name, Type type)
{
totalPlugin.Add(name, type);
}

public void SendMessage(string pluginName, string messageType, object[]? args = null)
{
if (!plugins.TryGetValue(pluginName, out var plugin))
{
if (totalPlugin.TryGetValue(pluginName, out var type))
{
plugin = Activator.CreateInstance(type) as Plugin;
if (plugin != null)
{
plugins.Add(pluginName, plugin);
}
}
}

if (plugin != null)
{
Operation operation = plugin.operations[0];
Type t = operation.GetType();
foreach (var method in t.GetMethods())
{
foreach (var attr in Attribute.GetCustomAttributes(method))
{
if (attr.GetType() == typeof(OperationAttribute))
{
method.Invoke(operation, args);
}
}
}
}
}
}

abstract class Plugin
{
public string name;
public List<Operation> operations = new List<Operation>();
public Model model;
public Plugin()
{
Init();
}

public void AddOperation(Operation operation)
{
operations.Add(operation);
}

protected abstract void Init();
}

[AttributeUsage(AttributeTargets.Method)]
class OperationAttribute : Attribute
{
public string funcName { get; set; }
public OperationAttribute(string funcName)
{
this.funcName = funcName;
}
}


class Operation
{

}

class Model
{

}

class UIPlugin : Plugin
{
protected override void Init()
{
this.AddOperation(new UIOperation());
}
}

class UIOperation : Operation
{
[Operation("OpenMainView")]
public void ShowUIMainView()
{
System.Console.WriteLine("ShowUIMainView");
}
}

class UIModel : Model
{

}

class GamePlugin : Plugin
{
protected override void Init()
{
this.AddOperation(new GameOperation());
}
}

class GameOperation : Operation
{
public void ShowGameMainView()
{
System.Console.WriteLine("ShowGameMainView");
}
}

class GameModel : Model
{

}