当前位置:   article > 正文

Unity MMO游戏架构设计之角色设计一_unity虚拟角色设计说明

unity虚拟角色设计说明

笔者介绍:姜雪伟,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类,也就是所有对象类的根,实现如下所示:

  1. public class BaseObject:MonoBehaviour
  2. {
  3. protected int m_Id;
  4. /// <summary>
  5. /// 标识移除后储存
  6. /// </summary>
  7. protected bool m_bRererveRemove;
  8. protected Dictionary<eCmd, OnMsgFunc> m_MsgFuncs = new Dictionary<eCmd, OnMsgFunc>();
  9. protected string m_Name;
  10. /// <summary>
  11. /// 对象类别
  12. /// </summary>
  13. protected EnumDefine.ObjType m_ObjType;
  14. protected int m_Uid;
  15. public virtual void Init(int uid)
  16. {
  17. this.m_Uid = uid;
  18. this.m_ObjType = EnumDefine.ObjType.None;
  19. this.m_MsgFuncs.Clear();
  20. }
  21. public virtual void Enable(Vector3 pos)
  22. {
  23. base.gameObject.transform.position = pos;
  24. this.m_bRererveRemove = false;
  25. }
  26. public virtual void Disable() { }
  27. public int GetId()
  28. {
  29. return this.m_Id;
  30. }
  31. public void SetName(string name)
  32. {
  33. this.m_Name = name;
  34. this.gameObject.name = name;
  35. }
  36. public string GetName()
  37. {
  38. return this.m_Name;
  39. }
  40. public EnumDefine.ObjType GetObjType()
  41. {
  42. return this.m_ObjType;
  43. }
  44. public int GetUid()
  45. {
  46. return this.m_Uid;
  47. }
  48. private void OnDestroy()
  49. {
  50. this.OnObjectDestroy();
  51. }
  52. public virtual void OnObjectDestroy() { }
  53. /// <summary>
  54. /// 执行指令
  55. /// </summary>
  56. /// <param name="cmd"></param>
  57. /// <param name="baseData"></param>
  58. public void OnObjMsg(eCmd cmd, IBaseMsgData baseData)
  59. {
  60. if (this.m_MsgFuncs.ContainsKey(cmd))
  61. {
  62. this.m_MsgFuncs[cmd](baseData);
  63. }
  64. }
  65. /// <summary>
  66. /// 注册消息指令
  67. /// </summary>
  68. /// <param name="cmd"></param>
  69. /// <param name="func"></param>
  70. protected void RegisterMsgHandler(eCmd cmd, OnMsgFunc func)
  71. {
  72. this.m_MsgFuncs.Add(cmd, func);
  73. }
  74. public void SetId(int id)
  75. {
  76. this.m_Id = id;
  77. }
  78. protected void Update()
  79. {
  80. this.UpdateObj(Time.deltaTime);
  81. }
  82. protected virtual void UpdateObj(float delta) { }
  83. public delegate void OnMsgFunc(IBaseMsgData bmd);
  84. }
这个类使用了对象消息函数OnObjMsg用于执行消息指令,ReginsterMsgHandler函数用于消息的添加,通过对象类的根可以看出,模块之间是通过

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

  1. public class BaseActor : BaseObject
  2. {
  3. /// <summary>
  4. /// AI 控制
  5. /// </summary>
  6. protected BaseAICtrl m_AiCtrl;
  7. /// <summary>
  8. /// 普通控制
  9. /// </summary>
  10. protected BaseCtrl m_Ctrl;
  11. protected bool m_bUpdateShineEff;
  12. /// <summary>
  13. /// 当前状态
  14. /// </summary>
  15. protected int m_CurState;
  16. /// <summary>
  17. /// 方位
  18. /// </summary>
  19. protected Vector3 m_Direction;
  20. /// <summary>
  21. /// 动画组件
  22. /// </summary>
  23. protected Animator animator;
  24. /// <summary>
  25. /// 模型fbx
  26. /// </summary>
  27. public GameObject m_FBX;
  28. /// <summary>
  29. /// 材质列表
  30. /// </summary>
  31. protected List<Material> m_Materials = new List<Material>();
  32. /// <summary>
  33. /// 上一状态
  34. /// </summary>
  35. protected int m_PrevState;
  36. /// <summary>
  37. /// 状态键值对
  38. /// </summary>
  39. protected Dictionary<int, StateFunc> m_StateFunc = new Dictionary<int, StateFunc>();
  40. /// <summary>
  41. /// 状态参数
  42. /// </summary>
  43. protected StateParam m_StateParam = new StateParam();
  44. protected float m_StateTimer;
  45. public override void Init(int uid)
  46. {
  47. base.Init(uid);
  48. this.m_StateFunc.Clear();
  49. this.RefreshMaterialInfo();
  50. if(this.m_FBX !=null)
  51. animator = this.m_FBX.GetComponent<Animator>();
  52. }
  53. public override void Enable(Vector3 pos)
  54. {
  55. base.Enable(pos);
  56. this.m_Direction = Vector3.forward;
  57. this.m_ShineValue = 0f;
  58. this.m_ShineTimer = 0f;
  59. this.m_bUpdateShineEff = false;
  60. this.m_PrevState = 0;
  61. this.m_CurState = 0;
  62. this.m_StateTimer = 0;
  63. }
  64. protected override void UpdateObj(float delta)
  65. {
  66. base.UpdateObj(delta);
  67. if (this.m_bUpdateShineEff)
  68. {
  69. UpdateShineEff(delta);
  70. }
  71. if (this.m_StateFunc.ContainsKey(this.m_CurState) && (this.m_StateFunc[this.m_CurState].updateFunc != null))
  72. {
  73. this.m_StateFunc[this.m_CurState].updateFunc(delta);
  74. }
  75. }
  76. /// <summary>
  77. /// 刷新材质球信息
  78. /// </summary>
  79. public void RefreshMaterialInfo()
  80. {
  81. this.m_Materials.Clear();
  82. SkinnedMeshRenderer[] smrs = gameObject.GetComponentsInChildren<SkinnedMeshRenderer>();
  83. for (int i = 0; i < smrs.Length; i++)
  84. {
  85. for (int k = 0; k < smrs[i].materials.Length; k++)
  86. {
  87. this.m_Materials.Add(smrs[i].materials[k]);
  88. }
  89. }
  90. MeshRenderer[] mrs = gameObject.GetComponentsInChildren<MeshRenderer>();
  91. for (int j = 0; j < mrs.Length; j++)
  92. {
  93. for (int m = 0; m < mrs[j].materials.Length; m++)
  94. {
  95. this.m_Materials.Add(mrs[j].materials[m]);
  96. }
  97. }
  98. }
  99. public void ChangeAnimSpeed(string aniName, float speed)
  100. {
  101. if (this.m_FBX.GetComponent<Animation>() != null)
  102. {
  103. this.m_FBX.GetComponent<Animation>()[aniName].speed = speed;
  104. }
  105. }
  106. public void SetCtrl(BaseCtrl ctrl)
  107. {
  108. this.m_Ctrl = ctrl;
  109. }
  110. public BaseCtrl GetCtrl()
  111. {
  112. return this.m_Ctrl;
  113. }
  114. public int GetCurState()
  115. {
  116. return this.m_CurState;
  117. }
  118. public Vector3 GetDirection()
  119. {
  120. return this.m_Direction;
  121. }
  122. public void Look(Vector3 dir)
  123. {
  124. if (dir != Vector3.zero)
  125. {
  126. dir.Normalize();
  127. base.gameObject.transform.localRotation = Quaternion.LookRotation(dir);
  128. this.m_Direction = dir;
  129. }
  130. }
  131. /// <summary>
  132. /// 注册动画事件
  133. /// </summary>
  134. /// <param name="aniName"></param>
  135. /// <param name="funcName"></param>
  136. /// <param name="time"></param>
  137. protected void RegisterAnimEvent(string aniName, string funcName, float time)
  138. {
  139. AnimationEvent evt = new AnimationEvent
  140. {
  141. time = time,
  142. functionName = funcName,
  143. intParameter = m_Uid
  144. };
  145. AnimationClip ac = this.m_FBX.GetComponent<Animation>().GetClip(aniName);
  146. if (ac == null)
  147. Debug.LogError("Not Found the AnimationClip:" + aniName);
  148. else
  149. this.m_FBX.GetComponent<Animation>().GetClip(aniName).AddEvent(evt);
  150. }
  151. /// <summary>
  152. /// 注册状态事件
  153. /// </summary>
  154. /// <param name="state"></param>
  155. /// <param name="enter"></param>
  156. /// <param name="update"></param>
  157. /// <param name="exit"></param>
  158. protected void RegistState(int state, StateFunc.EnterFunc enter, StateFunc.UpdateFunc update, StateFunc.ExitFunc exit)
  159. {
  160. StateFunc func = new StateFunc
  161. {
  162. enterFunc = enter,
  163. updateFunc = update,
  164. exitFunc = exit
  165. };
  166. this.m_StateFunc.Add(state, func);
  167. //Debug.Log("State:" + state);
  168. }
  169. /// <summary>
  170. /// 切换状态
  171. /// </summary>
  172. /// <param name="state"></param>
  173. /// <param name="param"></param>
  174. public void ChangeState(int state, StateParam param = null)
  175. {
  176. int curState = this.m_CurState;
  177. this.m_PrevState = curState;
  178. this.m_CurState = state;
  179. if (this.m_StateFunc.ContainsKey(curState) && (this.m_StateFunc[curState].exitFunc) != null)
  180. {
  181. this.m_StateFunc[curState].exitFunc();
  182. }
  183. if (this.m_StateFunc.ContainsKey(this.m_CurState) && (this.m_StateFunc[this.m_CurState].enterFunc) != null)
  184. {
  185. this.m_StateFunc[this.m_CurState].enterFunc(param);
  186. }
  187. this.m_StateTimer = 0f;
  188. }
  189. /// <summary>
  190. /// 转向
  191. /// </summary>
  192. /// <param name="angle"></param>
  193. /// <param name="delay"></param>
  194. public void Turn(float angle, float duration)
  195. {
  196. Quaternion rot = Quaternion.AngleAxis(angle, Vector3.up);
  197. TweenRotation.Begin(base.gameObject, duration, rot);
  198. this.m_Direction = (Vector3)(rot * Vector3.forward);
  199. }
  200. /// <summary>
  201. /// 转身
  202. /// </summary>
  203. /// <param name="targetPos"></param>
  204. /// <param name="delay"></param>
  205. public void Turn(Vector3 targetPos, float duration)
  206. {
  207. Vector3 forward = targetPos - gameObject.transform.position;
  208. Quaternion rot = Quaternion.LookRotation(forward);
  209. iTween.RotateTo (this.gameObject, iTween.Hash ("rotation", rot.eulerAngles, "time", duration, "easetype", "linear"));
  210. this.m_Direction = forward;
  211. }
  212. /// <summary>
  213. /// 动作播放New Mecanim System
  214. /// </summary>
  215. /// <param name="condition"></param>
  216. /// <param name="speed"></param>
  217. public void PlayAnim(string condition,float speed = 0f,float value=0,Type t = null)
  218. {
  219. animator.speed = speed;
  220. if (t == typeof(int))
  221. {
  222. animator.SetInteger(condition, (int)value);
  223. }
  224. else if (t == typeof(float))
  225. {
  226. animator.SetFloat(condition, value);
  227. }
  228. else
  229. {
  230. animator.SetTrigger(condition);
  231. }
  232. }
  233. }

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




声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/109261
推荐阅读
相关标签
  

闽ICP备14008679号