笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,CSDN社区专家,特邀编辑,畅销书作者,国家专利发明人;已出版书籍:《手把手教你架构3D游戏引擎》电子工业出版社和《Unity3D实战核心技术详解》电子工业出版社等。

CSDN视频网址:http://edu.csdn.net/lecturer/144

网上很多人问我关于MMO大型网络游戏中的架构设计,本篇博客主要是给读者介绍关于角色的设计,针对的是商业游戏中的结构设计,游戏中都会有英雄角色,这些英雄是受玩家控制的,这些英雄会随着版本的迭代而去扩充,这就需要我们在编写代码时要设计一个能扩充的架构。Unity自身提供了一个非常好的组件概念,每个对象身上可以挂接属于自己的组件,我们在设计角色架构时也是采用这种理念。架构没有好坏之分,只要能满足项目需求就可以了。

在Unity引擎中各个类的继承方式如下所示:

我们的角色设计也是参考Unity的类结构设计如下所示:

其中BaseObject是所有对象类的根,也就是祖宗级别,这个相当于Unity中的Object类,在它的下面是BaseActor类,从BaseActor类中延伸出两个儿子一个是3D的模型表示的BaseCharacter类和特效BaseEff类。

以前开发端游的时候,也是采用这种方式。针对BaseCharacter类,又延伸出两个继承类BaseHero和BaseMonster。BaseHero类再下面是具体的英雄类,比如武士,刺客,道士等英雄,BaseMonster类的子类是具体的怪物类。

接下来要去做控制类了,BaseCtrl,该类主要是用于控制上述实现的各个类。这个设计类似MVC中的C也就是是说Control,用于控制英雄和怪物或者特效。

用心的做架构设计目的是为了方便后期进行扩展,下面把实现的代码给读者展示如下:

在BaseActor前面还有一个父类是BaseObject类,作为BaseObject类,也就是所有对象类的根,实现如下所示:

   public class BaseObject:MonoBehaviour{protected int m_Id;/// <summary>/// 标识移除后储存/// </summary>protected bool m_bRererveRemove;protected Dictionary<eCmd, OnMsgFunc> m_MsgFuncs = new Dictionary<eCmd, OnMsgFunc>();protected string m_Name;/// <summary>/// 对象类别/// </summary>protected EnumDefine.ObjType m_ObjType;protected int m_Uid;public virtual void Init(int uid){this.m_Uid = uid;this.m_ObjType = EnumDefine.ObjType.None;this.m_MsgFuncs.Clear();}public virtual void Enable(Vector3 pos){base.gameObject.transform.position = pos;this.m_bRererveRemove = false;}public virtual void Disable() { }public int GetId(){return this.m_Id;}public void SetName(string name){this.m_Name = name;this.gameObject.name = name;}public string GetName(){return this.m_Name;}public EnumDefine.ObjType GetObjType(){return this.m_ObjType;}public int GetUid(){return this.m_Uid;}private void OnDestroy(){this.OnObjectDestroy();}public virtual void OnObjectDestroy() { }/// <summary>/// 执行指令/// </summary>/// <param name="cmd"></param>/// <param name="baseData"></param>public void OnObjMsg(eCmd cmd, IBaseMsgData baseData){if (this.m_MsgFuncs.ContainsKey(cmd)){this.m_MsgFuncs[cmd](baseData);}}/// <summary>/// 注册消息指令/// </summary>/// <param name="cmd"></param>/// <param name="func"></param>protected void RegisterMsgHandler(eCmd cmd, OnMsgFunc func){this.m_MsgFuncs.Add(cmd, func);}public void SetId(int id){this.m_Id = id;}protected void Update(){this.UpdateObj(Time.deltaTime);}protected virtual void UpdateObj(float delta) { }public delegate void OnMsgFunc(IBaseMsgData bmd);}

这个类使用了对象消息函数OnObjMsg用于执行消息指令,ReginsterMsgHandler函数用于消息的添加,通过对象类的根可以看出,模块之间是通过

消息执行的。实现完了对象的根,接下来实现BaseActor类,下面把类的具体实现给读者展示如下:

    public class BaseActor : BaseObject{/// <summary>/// AI 控制/// </summary>protected BaseAICtrl m_AiCtrl;/// <summary>/// 普通控制/// </summary>protected BaseCtrl m_Ctrl;protected bool m_bUpdateShineEff;/// <summary>/// 当前状态/// </summary>protected int m_CurState;/// <summary>/// 方位/// </summary>protected Vector3 m_Direction;/// <summary>/// 动画组件/// </summary>protected Animator animator;/// <summary>/// 模型fbx/// </summary>public GameObject m_FBX;/// <summary>/// 材质列表/// </summary>protected List<Material> m_Materials = new List<Material>();/// <summary>/// 上一状态/// </summary>protected int m_PrevState;/// <summary>/// 状态键值对/// </summary>protected Dictionary<int, StateFunc> m_StateFunc = new Dictionary<int, StateFunc>();/// <summary>/// 状态参数/// </summary>protected StateParam m_StateParam = new StateParam();protected float m_StateTimer;public override void Init(int uid){base.Init(uid);this.m_StateFunc.Clear();this.RefreshMaterialInfo();if(this.m_FBX !=null)animator = this.m_FBX.GetComponent<Animator>();}public override void Enable(Vector3 pos){base.Enable(pos);this.m_Direction = Vector3.forward;this.m_ShineValue = 0f;this.m_ShineTimer = 0f;this.m_bUpdateShineEff = false;this.m_PrevState = 0;this.m_CurState = 0;this.m_StateTimer = 0;}protected override void UpdateObj(float delta){base.UpdateObj(delta);if (this.m_bUpdateShineEff){UpdateShineEff(delta);}if (this.m_StateFunc.ContainsKey(this.m_CurState) && (this.m_StateFunc[this.m_CurState].updateFunc != null)){this.m_StateFunc[this.m_CurState].updateFunc(delta);}}/// <summary>/// 刷新材质球信息/// </summary>public void RefreshMaterialInfo(){this.m_Materials.Clear();SkinnedMeshRenderer[] smrs = gameObject.GetComponentsInChildren<SkinnedMeshRenderer>();for (int i = 0; i < smrs.Length; i++){for (int k = 0; k < smrs[i].materials.Length; k++){this.m_Materials.Add(smrs[i].materials[k]);}}MeshRenderer[] mrs = gameObject.GetComponentsInChildren<MeshRenderer>();for (int j = 0; j < mrs.Length; j++){for (int m = 0; m < mrs[j].materials.Length; m++){this.m_Materials.Add(mrs[j].materials[m]);}}}public void ChangeAnimSpeed(string aniName, float speed){if (this.m_FBX.GetComponent<Animation>() != null){this.m_FBX.GetComponent<Animation>()[aniName].speed = speed;}}public void SetCtrl(BaseCtrl ctrl){this.m_Ctrl = ctrl;}public BaseCtrl GetCtrl(){return this.m_Ctrl;}public int GetCurState(){return this.m_CurState;}public Vector3 GetDirection(){return this.m_Direction;}public void Look(Vector3 dir){if (dir != Vector3.zero){dir.Normalize();base.gameObject.transform.localRotation = Quaternion.LookRotation(dir);this.m_Direction = dir;}}/// <summary>/// 注册动画事件/// </summary>/// <param name="aniName"></param>/// <param name="funcName"></param>/// <param name="time"></param>protected void RegisterAnimEvent(string aniName, string funcName, float time){AnimationEvent evt = new AnimationEvent{time = time,functionName = funcName,intParameter = m_Uid};AnimationClip ac = this.m_FBX.GetComponent<Animation>().GetClip(aniName);if (ac == null)Debug.LogError("Not Found the AnimationClip:" + aniName);elsethis.m_FBX.GetComponent<Animation>().GetClip(aniName).AddEvent(evt);}/// <summary>/// 注册状态事件/// </summary>/// <param name="state"></param>/// <param name="enter"></param>/// <param name="update"></param>/// <param name="exit"></param>protected void RegistState(int state, StateFunc.EnterFunc enter, StateFunc.UpdateFunc update, StateFunc.ExitFunc exit){StateFunc func = new StateFunc{enterFunc = enter,updateFunc = update,exitFunc = exit};this.m_StateFunc.Add(state, func);//Debug.Log("State:" + state);}/// <summary>/// 切换状态 /// </summary>/// <param name="state"></param>/// <param name="param"></param>public void ChangeState(int state, StateParam param = null){int curState = this.m_CurState;this.m_PrevState = curState;this.m_CurState = state;if (this.m_StateFunc.ContainsKey(curState) && (this.m_StateFunc[curState].exitFunc) != null){this.m_StateFunc[curState].exitFunc();}if (this.m_StateFunc.ContainsKey(this.m_CurState) && (this.m_StateFunc[this.m_CurState].enterFunc) != null){this.m_StateFunc[this.m_CurState].enterFunc(param);}this.m_StateTimer = 0f;}/// <summary>/// 转向/// </summary>/// <param name="angle"></param>/// <param name="delay"></param>public void Turn(float angle, float duration){Quaternion rot = Quaternion.AngleAxis(angle, Vector3.up);TweenRotation.Begin(base.gameObject, duration, rot);this.m_Direction = (Vector3)(rot * Vector3.forward);}/// <summary>/// 转身/// </summary>/// <param name="targetPos"></param>/// <param name="delay"></param>public void Turn(Vector3 targetPos, float duration){Vector3 forward = targetPos - gameObject.transform.position;Quaternion rot = Quaternion.LookRotation(forward);iTween.RotateTo (this.gameObject, iTween.Hash ("rotation", rot.eulerAngles, "time", duration, "easetype", "linear"));this.m_Direction = forward;}/// <summary>/// 动作播放New Mecanim System/// </summary>/// <param name="condition"></param>/// <param name="speed"></param>public void PlayAnim(string condition,float speed = 0f,float value=0,Type t = null){animator.speed = speed;if (t == typeof(int)){animator.SetInteger(condition, (int)value);              }else if (t == typeof(float)){animator.SetFloat(condition, value);}else{animator.SetTrigger(condition);}            }}

该类主要实现了类的注册状态和切换状态,以及动画注册事件。。。。。。。。。。

Unity MMO游戏架构设计之角色设计一相关推荐

  1. 游戏脚本在移动游戏设计中的作用_关卡设计师谈游戏中的敌对角色设计Monster Design...

    原作者:Emil Glans 关卡设计是一门非常广泛的学科,不仅涵盖了基础几何学.脚本中的事件&敌人设计,还涉及到不同部分的组合.紧张度调节和叙事.在本文中,我将重点讨论一些与核心游戏设计密切 ...

  2. 关卡设计_关卡设计与环境设计

    关卡设计 Creating the game space for the player to explore is another aspect of game development that ca ...

  3. 地球那么大的开放世界游戏怎么做?腾讯云高级架构师为开发者设计了一套方案

    Unity全球开发者大会Unite Shanghai 2019在上海召开,期间诸多技术专家来到现场为开发者分享主题多元的技术演讲以及行业趋势分析. 腾讯云互联网行业架构师余多,在大会期间进行了&quo ...

  4. Unity 3D 环境特效||Unity 3D 游戏场景设计实例

    Unity 3D 环境特效 一般情况下,要在游戏场景中添加雾特效和水特效较为困难,因为需要开发人员懂得着色器语言且能够熟练地使用它进行编程. Unity 3D 游戏开发引擎为了能够简单地还原真实世界中 ...

  5. 【Unity】第三人称射击游戏开发过程之瞄准状态设计(TPS.S.P1)

    [Unity]第三人称射击游戏开发过程之瞄准状态设计(TPS.S.P1) 设计整体的结构与模式 瞄准状态的设计 瞄准相机 瞄准状态 瞄准时的鼠标移动速度限制 瞄准点的处理 角色在瞄准状态下的旋转 瞄准 ...

  6. 关于游戏架构设计(二)

    架构设计目录二 UI架构 基类BaseWindow Control控制类 State状态接口 窗口管理类 状态管理类 角色系统 角色系统设计的框架图 角色实体类父类 IEntity 有限状态机接口En ...

  7. 如何实现游戏架构设计

    1.什么是架构设计 最近公司招人,我负责面试程序员,人事发给我很多简历,我在阅读他们的简历时,经常会看到说自己会客户端架构设计,但当问到他们什么是架构设计时,基本上是一无所知.出现这种情况原因:一是自 ...

  8. 游戏架构设计的一些整理

    一个大型的网落游戏服务器应该包含几个模块:网络通讯,业务逻辑,数据存储,守护监控(不是必须),其中业务逻辑可能根据具体需要,又划分为好几个子模块. 这里说的模块可以指一个进程,或者一个线程方式存在,本 ...

  9. [转]关于游戏架构设计的一些整理吧

    一个大型的网落游戏服务器应该包含几个模块:网络通讯,业务逻辑,数据存储,守护监控(不是必须),其中业务逻辑可能根据具体需要,又划分为好几个子模块. 这里说的模块可以指一个进程,或者一个线程方式存在,本 ...

  10. 来自Riot 的一份游戏美术教程(三):角色设计

    引言 前段时间,Riot Games推出了一个针对游戏美术的系列视频:So you wanna make games??这一系列的特点是短小精悍,每集只有十分钟,却囊括了游戏美术的各个方面,对于新手来 ...

最新文章

  1. Ubuntu下添加新分区并设置挂载点
  2. 下拉框处理(select)
  3. 论软件的模块化与架构
  4. python3.5安装tensorflow_pip install tensorflowgpu在python3.5中的安装
  5. CSS3特效 - 呼吸灯效果
  6. Java基础知识强化21:Java中length、length()、size()区别
  7. 定义斜体文本的html标签,HTML 文本格式化
  8. 如何在股票软件画波浪?波浪原理?初级应用画线
  9. ANSYS Maxwell 2D永磁体建模
  10. 【labelme】制作标签数据的完整流程
  11. Horizontalscrollview
  12. Word文字怎么居中对齐
  13. 微积分——傅里叶级数
  14. 获取前N天/月/年的日期
  15. 7z解压crc错误_百度网盘压缩下载文件的CRC校验错误的解决方法
  16. sflow-rt 3.0 安装
  17. Linux断开usb调试命令,Android关闭USB的ADB调试和文件传输功能(禁用USB)【转】
  18. AOP技术介绍--(AOP技术基础)
  19. 阿里测试工程师聊:软件测试需要学什么?
  20. Android 引入布局

热门文章

  1. windows虚机使用IIS服务搭建ftp
  2. php把数组作为函数参数传递,使用关联数组作为函数的参数《 PHP 基础 》
  3. Android学习日记(yzy):SQLite数据库和baseAdapter
  4. kotlin expecting a top leveleclaration
  5. vue全家桶指的是哪些?
  6. 嵌入式技术学习路线分享
  7. Unity网络编程教学视频(本人第一次录制)
  8. Referenced file contains errors解决
  9. 深入理解操作系统实验——bomb lab(secret_phase)
  10. 如何平衡MMO游戏 ——Einsphoton