来说说组件(Components)模式

来源:互联网 发布:windows源代码谁写的 编辑:程序博客网 时间:2024/06/11 09:45

1.什么是组件模式?通俗点讲,我觉得他像一个机械工程一样,像飞机,潜艇,他有许多的零件系统组成,各个零件部门相互独立,独立来加工,等把需要的组件零件都加工生产完成之后,由组装师组成一个完整的个体,而要启动这个整体飞机要起飞,潜艇要发射炮弹,各个系统组件都协调有序的运行起来。而这些组件又想独立于系统,随时可以进行更换,进行升级。
3,游戏中最常见的就是任务角色的设计,组件模式用的比较多,还有就是slg类的游戏,像建筑的升级,城堡的建设等等。我们今天来实现一个人物角色的组件设计模式。一个Avatar通常可以飞,可以跑,可能会受到伤害,可以攻击别人,这样我们都可以把这些行为作为一个组件,然后我们一个角色就可以随意的来进行组合,来达到我们要的效果。

2.在游戏中是怎么使用的?现在的游戏中大量的用到了组件模式,他比继承更具有解偶性。他更加的方便维护,来进行开发,一个好的游戏系统设计出来,当引擎无论的怎么更替,业务逻辑怎么样的变更,仍然能够井井有序思路清晰的来开发,并且bug率很少,好多比较次的游戏系统中一个文件的代码达到好几千行,像这样看着都费劲,更别说可读性了,从而整个开发的效率成几何一样的下降,并且全是bug,这样你很难去管理,同时坑队友。

我们创建一个实体EntityBase类,来作为一个主体。

using System;using System.Collections.Generic;using UnityEngine;public class EntityBase{public IDictionary<string ,ComponentBase> componentMaps = new Dictionary<string,ComponentBase>(); /// <summary>/// 加入组件方法/// </summary>/// <param name="key">Key.</param>/// <param name="comptBase">Compt base.</param>public void AddComponent(string key,ComponentBase  comptBase){if (comptBase == null) {Debug.Log ("add component failed: comptbase == null");}if(!componentMaps.ContainsKey(key)){componentMaps.Add (key,comptBase);this.AttachedComponent (comptBase);comptBase.AddFromEntity (this);}}/// <summary>///通过Key值来删除组件/// </summary>/// <param name="key">Key.</param>public  void RemoveComponent(string key){if(componentMaps.ContainsKey(key)){this.RemovedComponent (componentMaps[key]);componentMaps [key].RemovFromEntity (this);componentMaps.Remove (key);}}///<summary>/// 发送事件/// </summary>/// public bool DispatchEvent(Event events){bool flag_1 = false;//发送一个时间   看cpt 对象那些注册该时间,注册了则进行调用foreach(ComponentBase  pts in componentMaps.Values){//怎么知道有没有注册改事件  注册成功就会调用各个组件的方法 返回TRUE 则为调用成功,执行成功bool flag = pts.OnEvent (events);flag_1 = (flag_1 || flag);}if (flag_1 == false) {Debug.Log ("Dispatch falies!");}return flag_1;}/// <summary>/// 添加成功了组件回调/// </summary>/// <param name="cptBase">Cpt base.</param>public virtual void AttachedComponent(ComponentBase cptBase){}/// <summary>/// 移除成功了改组件/// </summary>/// <param name="cptBase">Cpt base.</param>public virtual void RemovedComponent(ComponentBase cptBase){}}


再来创建一个component的基础类

using System;using System.Collections.Generic;public class ComponentBase{protected EntityBase entityBase;public  delegate  void  EventHandleFunction(Event events); private Dictionary<int,EventHandleFunction> EventHandlerMap = new Dictionary<int,EventHandleFunction>();///<summary>/// 向entity上面添加了此组件/// </summary>public virtual void AddFromEntity(EntityBase entityBase){entityBase = entityBase;}/// <summary>/// 从entity移除了该组件/// </summary>public virtual void RemovFromEntity(EntityBase ety){entityBase = null;}/// <summary>///看有没有注册该事件/// </summary>/// <returns><c>true</c>, if event was oned, <c>false</c> otherwise.</returns>/// <param name="events">Events.</param>public bool OnEvent(Event events){EventHandleFunction handerFunction;//有没有注册改类事件if(EventHandlerMap.TryGetValue(events.event_id, out handerFunction) == false){return false;}if(handerFunction == null){return false;}handerFunction (events);return true;}///<summary>/// 注册事件/// </summary>public void RegistEvent(int eventID,EventHandleFunction  handlerFunction){if(EventHandlerMap.ContainsKey(eventID)){EventHandlerMap.Remove (eventID);}EventHandlerMap.Add(eventID,handlerFunction);}/// <summary>/// 移除注册的事件/// </summary>/// <param name="eventID">Event I.</param>/// <param name="handlerFunction">Handler function.</param>public void UnRegistEvent(int eventID){if(EventHandlerMap.ContainsKey(eventID)){EventHandlerMap.Remove (eventID);}}}
组件和实体怎么通信的,我们来创建一个通信的事件类

using System;using System.Collections;using System.Collections.Generic;using System.Linq;using UnityEngine;public class Event{public int event_id;ArrayList eventArags = new ArrayList(); public void pushUserData<T>( T Data){eventArags.Add (Data);}public T getUserData<T>(int event_id){if(event_id > eventArags.Count){return default(T);}return (T)eventArags[event_id];}}

在来创建一个事件类型的枚举

using System;public enum EventDefine{Event_01 = 0,Event_02,Event_03,Event_04,}


好了我们基本的封装底层基本上已经实现了,我们来做个测试,我们分别来创建一个FlyComponent 和 RuningComponent 的组件


using System;using UnityEngine;public class FlyComponent :ComponentBase{public override void AddFromEntity(EntityBase entityBase){base.AddFromEntity (entityBase);RegistEvent ((int)(EventDefine.Event_01),DealEvent01);RegistEvent ((int)(EventDefine.Event_03),DealEvent03);}public override void RemovFromEntity(EntityBase ety){base.RemovFromEntity (ety);}private void DealEvent01(Event evt){string evtData = evt.getUserData<string>(0);Debug.Log("FlyComponent Handle Event: ID = " + evt.event_id.ToString());Debug.Log("FlyComponent Handle Event: Data = " + evtData);Debug.Log("我开始飞起来了================");}private void DealEvent03(Event evt){float evtData = evt.getUserData<float>(0);Debug.Log("FlyComponent Handle Event: ID = " + evt.event_id.ToString());Debug.Log("FlyComponent Handle Event: Data = " + evtData);Debug.Log("飞啊  飞啊 ================");}}

using System;using UnityEngine;public class RuningComponent : ComponentBase{public override void AddFromEntity(EntityBase entityBase){base.AddFromEntity (entityBase);RegistEvent ((int)(EventDefine.Event_02),Event_02);RegistEvent ((int)(EventDefine.Event_04),Event_04);}public override void RemovFromEntity(EntityBase ety){base.RemovFromEntity (ety);}private void Event_02(Event evt){string evtData = evt.getUserData<string>(0);Debug.Log("RuningComponent Handle Event: ID = " + evt.event_id.ToString());Debug.Log("RuningComponent Handle Event: Data = " + evtData);Debug.Log("跑起来了  跑起来了================");}private void Event_04(Event evt){float evtData = evt.getUserData<float>(0);Debug.Log("RuningComponent Handle Event: ID = " + evt.event_id.ToString());Debug.Log("RuningComponent Handle Event: Data = " + evtData);Debug.Log("跑啊跑啊  跑================");}}

再来创建一个Avatar实体类

using System;public class AvatarEntity  : EntityBase{public AvatarEntity(){InitComponents ();}public void InitComponents(){FlyComponent flyComp = new FlyComponent();AddComponent("FlyComponent", flyComp);RuningComponent runComp = new RuningComponent();AddComponent("RuningComponent", runComp);}/// <summary>/// 调用跑的接口/// </summary>public virtual void Fly(){// 发送消息Event_01Event evt1 = new Event();evt1.event_id = (int)EventDefine.Event_01;evt1.pushUserData<string>("SomeData For Event01");DispatchEvent(evt1);}/// <summary>/// 开始跑了/// </summary>public virtual void Runing(){// 发送消息Event_02Event evt2 = new Event();evt2.event_id = (int)EventDefine.Event_02;evt2.pushUserData<string>("SomeData For Event02");DispatchEvent(evt2);}}



大功告成,我们来直接测试了

//测试组件模式var  avatEntity =  new AvatarEntity ();avatEntity.Fly ();//飞起来了avatEntity.Runing ();//跑了