技能架构设计
来源:互联网 发布:虚拟拍照软件 编辑:程序博客网 时间:2024/05/17 11:35
我想把技能做的比较牛逼,所以项目一开始我就在思考,是否需要一个灵活自由的技能系统架构设计,传统的技能设计,做法都是填excel表,技能需要什么,都填表里,很死板,比如有的技能只需要1个特效,有的要10个,那么表格也得预留10个特效的字段.在代码里面也是写死一些东西,要增加和修改,就得改核心代码,如果我要把核心部分做成库封装起来,就很麻烦了.
能不能做成数据驱动的方式呢?
改技能文件就行了,即使要增加功能,也只需要扩展外部代码,而不用改核心代码,
我是这么来抽象一个技能的,技能由一堆触发器组成,比如特效触发器,动作触发器,声音触发器,摄像机震动触发器等等,这些触发器到了某个条件就执行触发,触发条件一般是时间,如果有比较复杂的浮空技能,可以增加落地触发等.
自定义一个技能文件,代替excel表格,看起来是这样:
简单的技能:
每一行都是一个触发器,这些触发器,到了某个条件会自动触发.
上面的意思就是,第0秒开始面向目标,第0秒开始播放动作1000
复杂的技能:
这个技能能将目标打到空中,并完成3连击,然后从空中砸向地面,
CurveMove(0, 0.413, 104, 0, 0, 0, 0);的意思就是,第0.413秒,开始做曲线运动,让角色飞到空中,曲线运动的ID是104,
用这样的文件来配置一个技能,很灵活,也很快,
- private bool ParseScript(string filename)
- {
- bool ret = false;
- try
- {
- StreamReader sr = FileReaderProxy.ReadFile(filename);
- if (sr != null)
- ret = LoadScriptFromStream(sr);
- }
- catch (Exception e)
- {
- string err = “Exception:” + e.Message + “\n” + e.StackTrace + “\n”;
- LogSystem.ErrorLog(err);
- }
- return ret;
- }
- private bool LoadScriptFromStream(StreamReader sr)
- {
- bool bracket = false;
- SkillInstance skill = null;
- do
- {
- string line = sr.ReadLine();
- if (line == null)
- break;
- line = line.Trim();
- if (line.StartsWith(“//”) || line == “”)
- continue;
- if (line.StartsWith(“skill”))
- {
- int start = line.IndexOf(“(“);
- int end = line.IndexOf(“)”);
- if (start == -1 || end == -1)
- LogSystem.ErrorLog(”ParseScript Error, start == -1 || end == -1 {0}”, line);
- int length = end - start - 1;
- if (length <= 0)
- {
- LogSystem.ErrorLog(”ParseScript Error, length <= 1, {0}”, line);
- return false;
- }
- string args = line.Substring(start + 1, length);
- int skillId = (int)Convert.ChangeType(args, typeof(int));
- skill = new SkillInstance();
- AddSkillInstanceToPool(skillId, skill, true);
- }
- else if (line.StartsWith(“{“))
- {
- bracket = true;
- }
- else if (line.StartsWith(“}”))
- {
- bracket = false;
- // 按时间排序
- skill.m_SkillTrigers.Sort((left, right) =>
- {
- if (left.GetStartTime() > right.GetStartTime())
- {
- return -1;
- }
- else if (left.GetStartTime() == right.GetStartTime())
- {
- return 0;
- }
- else
- {
- return 1;
- }
- });
- }
- else
- {
- // 解析trigger
- if (skill != null && bracket == true)
- {
- int start = line.IndexOf(“(“);
- int end = line.IndexOf(“)”);
- if (start == -1 || end == -1)
- LogSystem.ErrorLog(”ParseScript Error, {0}”, line);
- int length = end - start - 1;
- if (length <= 0)
- {
- LogSystem.ErrorLog(”ParseScript Error, length <= 1, {0}”, line);
- return false;
- }
- string type = line.Substring(0, start);
- string args = line.Substring(start + 1, length);
- args = args.Replace(” ”, “”);
- ISkillTrigger trigger = SkillTriggerMgr.Instance.CreateTrigger(type, args);
- if (trigger != null)
- {
- skill.m_SkillTrigers.Add(trigger);
- }
- }
- }
- } while (true);
- return true;
- }
private bool ParseScript(string filename) { bool ret = false; try { StreamReader sr = FileReaderProxy.ReadFile(filename); if (sr != null) ret = LoadScriptFromStream(sr); } catch (Exception e) { string err = "Exception:" + e.Message + "\n" + e.StackTrace + "\n"; LogSystem.ErrorLog(err); } return ret; } private bool LoadScriptFromStream(StreamReader sr) { bool bracket = false; SkillInstance skill = null; do { string line = sr.ReadLine(); if (line == null) break; line = line.Trim(); if (line.StartsWith("//") || line == "") continue; if (line.StartsWith("skill")) { int start = line.IndexOf("("); int end = line.IndexOf(")"); if (start == -1 || end == -1) LogSystem.ErrorLog("ParseScript Error, start == -1 || end == -1 {0}", line); int length = end - start - 1; if (length <= 0) { LogSystem.ErrorLog("ParseScript Error, length <= 1, {0}", line); return false; } string args = line.Substring(start + 1, length); int skillId = (int)Convert.ChangeType(args, typeof(int)); skill = new SkillInstance(); AddSkillInstanceToPool(skillId, skill, true); } else if (line.StartsWith("{")) { bracket = true; } else if (line.StartsWith("}")) { bracket = false; // 按时间排序 skill.m_SkillTrigers.Sort((left, right) => { if (left.GetStartTime() > right.GetStartTime()) { return -1; } else if (left.GetStartTime() == right.GetStartTime()) { return 0; } else { return 1; } }); } else { // 解析trigger if (skill != null && bracket == true) { int start = line.IndexOf("("); int end = line.IndexOf(")"); if (start == -1 || end == -1) LogSystem.ErrorLog("ParseScript Error, {0}", line); int length = end - start - 1; if (length <= 0) { LogSystem.ErrorLog("ParseScript Error, length <= 1, {0}", line); return false; } string type = line.Substring(0, start); string args = line.Substring(start + 1, length); args = args.Replace(" ", ""); ISkillTrigger trigger = SkillTriggerMgr.Instance.CreateTrigger(type, args); if (trigger != null) { skill.m_SkillTrigers.Add(trigger); } } } } while (true); return true; }
文件的解析,也很简单
那么从代码上怎么实现呢?
1.触发器:
从同一个基类继承,
2.工厂模式来创建注册触发器,
在外部注册触发器的代码:
3.技能实例来管理触发器,
执行触发其实也可以写这里.
4.技能系统来管理所有技能
技能是可以复用的,技能系统就是一个技能池子,不停地new技能实例和回收技能实例
部分Public 接口代码:
总结一下思路,就是
SkillSystem 管理SkillInstance,创建和回收所有技能
SkillInstance 管理 SkillTrigger,负责触发器的触发.
SkillTrigger 就执行具体的效果.
- 技能架构设计
- 系统架构技能之设计模式-全
- 技能设计新手入门(架构参考用)
- 系统架构技能之设计模式—工厂模式
- 系统架构技能之设计模式-单件模式
- 系统架构技能之设计模式-工厂模式
- 系统架构技能之设计模式-抽象工厂模式
- 系统架构技能之设计模式—装饰模式
- 系统架构技能之设计模式—工厂模式
- 系统架构技能之设计模式—装饰模式
- 系统架构技能之设计模式-单件模式
- 系统架构技能之设计模式-工厂模式
- Unity3D手游开发日记(2) - 技能系统架构设计
- Unity教程之-Unity游戏技能Skill系统架构设计
- 技能设计
- 架构师技能图谱
- 《炉石传说》架构设计赏析(5):卡牌&技能的静态数据组织
- 《炉石传说》架构设计赏析(6):卡牌&技能数据的运行时组织
- Java运算符
- 第二周 项目1
- iOS运行App总是提示Unknown class in Interface Builder file的解决
- 2017 ACMICPC Asia Regional Qingdao Online 1001 Apple
- 感知器在matlab中应用
- 技能架构设计
- 关于Mac上使用百度云下载速度慢的解决方案
- es5中严格模式相关问题
- HDU
- Ubuntu新手入门全攻略
- Android AsyncTask 源码解析
- C语言笔记——gets_s, fgets, puts函数
- Tensorflow-get_variable、Variable
- oracle表查询(六)