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 {
}
|