赞
踩
笔者介绍:姜雪伟,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);
- else
- this.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);
- }
- }
-
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。