Unity 自定义事件

来源:互联网 发布:arm-linux-gcc是什么 编辑:程序博客网 时间:2024/05/17 20:24

Unity 自定义事件


EventId.cs
using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace Assets.Scripts.Event{    //事件ID    public enum EventId    {        event1,        event2,        Count,//必须写在最后 用于表示所有Event的个数以及存储时间数组长度    }}

EventEatResponse.cs

using UnityEngine;using System.Collections;namespace Assets.Scripts.Event{    public enum EventEatResponse    {        /// 继续向下一个已经注册该事件的游戏体传递当前事件        NotEaten,        /// 停止向下一个已经注册该事件的游戏体传递当前事件        Eaten,    }}

EventObservers.cs
using System;using System.Collections.Generic;using System.Linq;using System.Text;using Assets.Scripts.DataStructures;using Assets.Scripts.Core;namespace Assets.Scripts.Event{    /// <summary>    /// 事件监听列表    /// </summary>    public class EventObservers    {        public PriorityList<IEventObserver> List { get; private set; }               public MutableIterator Iter { get; private set; }        public EventObservers()        {            List = new PriorityList<IEventObserver>();            Iter = new MutableIterator();        }    }}

EventPriority.cs
using UnityEngine;using System.Collections;namespace Assets.Scripts.Event{    /// <summary>    /// 事件优先级    /// </summar>    public enum EventPriority    {                AfterDefault,        Default,        BeforeDefault,        Notification,    }}

IEventObserver.cs
using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace Assets.Scripts.Event{    /// <summary>    /// 事件接口  所有要注册事件的类都要实现    /// </summary>    ///         public interface IEventObserver    {        // 接到事件后会调用该接口        EventEatResponse OnEvent(EventId id, object cookie);    }}

EventManager.cs
using System;using System.Collections.Generic;using System.Linq;using System.Text;using Assets.Scripts.Core;using Assets.Scripts.DataStructures;namespace Assets.Scripts.Event{    /// <summary>    /// 事件管理类    /// </summary>    public class EventManager    {        //已经注册事件的游戏体列表  根据事件优先级分组        private EventObservers[] eventIdToObservers;        public EventManager()        {            Service.Set<EventManager>(this);            int count = (int)EventId.Count;            eventIdToObservers = new EventObservers[count];            // Fill with nulls until someone decides to listen for a given event.            // .Net does this for us.  Just being explicit.            for (int i = 0; i < count; i++)            {                eventIdToObservers[i] = null;            }        }        // 注册默认优先级别的事件        public void RegisterObserver(IEventObserver observer, EventId id)        {            RegisterObserver(observer, id, EventPriority.Default);        }        // 根据优先级来注册事件        public void RegisterObserver(IEventObserver observer, EventId id, EventPriority priority)        {            if (observer == null)            {                return;            }            int index = (int)id;            EventObservers observers = eventIdToObservers[index];            if (observers == null)            {                observers = new EventObservers();                eventIdToObservers[index] = observers;            }            PriorityList<IEventObserver> list = observers.List;            if (list.IndexOf(observer) < 0)            {                list.Add(observer, (int)priority);            }        }        // 根据id接触已经注册的事件        public void UnregisterObserver(IEventObserver observer, EventId id)        {            int index = (int)id;            EventObservers observers = eventIdToObservers[index];            if (observers != null)            {                PriorityList<IEventObserver> list = observers.List;                MutableIterator miter = observers.Iter;                int i = list.IndexOf(observer);                if (i >= 0)                {                    list.RemoveAt(i);                    miter.OnRemove(i);                    if (list.Count == 0)                    {                        eventIdToObservers[index] = null;                    }                }            }        }        // 根据ID发送事件        public void SendEvent(EventId id, object cookie)        {            int index = (int)id;            EventObservers observers = eventIdToObservers[index];            if (observers != null)            {                PriorityList<IEventObserver> list = observers.List;                MutableIterator miter = observers.Iter;                for (miter.Init(list.Count); miter.Active(); miter.Next())                {                    IEventObserver observer = list.GetElement(miter.Index);                    if (observer.OnEvent(id, cookie) == EventEatResponse.Eaten)                    {                        break;                    }                }                miter.Reset();            }        }    }}
ElementPriorityPair.cs
using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace Assets.Scripts.Event{    public class ElementPriorityPair<T>    {        public T Element { get; set; }        public int Priority { get; set; }        public ElementPriorityPair(T element, int priority)        {            Element = element;            Priority = priority;        }    }}

MutableIterator.cs
using System;using System.Collections.Generic;using System.Collections;using System.Linq;using System.Text;namespace Assets.Scripts.Event{    public class MutableIterator    {        int index;        int count;        public MutableIterator()        {            Reset();        }        public void Reset()        {            index = 0;            count = 0;        }        public void Init(int count)        {            index = 0;            this.count = count;        }        public void Init(ICollection list)        {            index = 0;            this.count = list.Count;        }        public bool Active()        {            return index < count;        }        public void Next()        {            index++;        }        public int Index        {            get { return index; }            set            {                // Only allow manual index setting if we haven't yet started iterating.                if (index == 0)                {                    index = value;                }            }        }        public int Count        {            get { return count; }        }        public void OnRemove(int i)        {            if (count > 0)            {                count--;                if (i <= index)                {                    index--;                }            }        }    }}

PriorityList.cs
using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace Assets.Scripts.Event{    public class PriorityList<T>    {        private List<ElementPriorityPair<T>> list;        public PriorityList()        {            list = new List<ElementPriorityPair<T>>();        }        // Just like List<T>.Count.        public int Count        {            get { return list.Count; }        }        // Similar to List<T>.Add() but inserts based on priority.        // Returns the index where the element was inserted.        // Returns -1 on failure.        public virtual int Add(T element, int priority)        {            // Prevent null from being added.  It's just one of the features of this class.            if (element == null)            {                return -1;            }            for (int i = 0, count = list.Count; i < count; i++)            {                ElementPriorityPair<T> pair = list[i];                if (object.ReferenceEquals(pair.Element, element))                {                    // Already added.                    return -1;                }                // Keep the list sorted, higher priority first.                // For equal priorities, we'll add ourselves to the end of that range.                if (priority > pair.Priority)                {                    // Found insertion point.                    list.Insert(i, new ElementPriorityPair<T>(element, priority));                    return i;                }            }            // Didn't find an insertion point.  Add new currently-lowest-priority element.            list.Add(new ElementPriorityPair<T>(element, priority));            return list.Count - 1;        }        public ElementPriorityPair<T> Get(int i)        {            return list[i];        }        // Similar to List<T>[i].        public T GetElement(int i)        {            return list[i].Element;        }        // Get the associated prioriity of the i'th element.        public int GetPriority(int i)        {            return list[i].Priority;        }        // Alternative for when you want both the element and its associated prioiryt.        public void GetElementPriority(int i, out T element, out int priority)        {            ElementPriorityPair<T> pair = list[i];            element = pair.Element;            priority = pair.Priority;        }        // Just like List<T>.IndexOf(element).        public int IndexOf(T element)        {            for (int i = 0, count = list.Count; i < count; i++)            {                if (object.ReferenceEquals(list[i].Element, element))                {                    return i;                }            }            return -1;        }        // No Remove(T t), to discourage misuse.  Callers must know the index to remove.        // Remove(T t) can always be implemented is "if ((i = IndexOf(t)) >= 0) RemoveAt(i);".        public void RemoveAt(int i)        {            list.RemoveAt(i);        }    }}

Service.cs
using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace Assets.Scripts.Event{    public static class Service    {#if SERVER        [ThreadStatic]#endif        private static List<IServiceWrapper> serviceWrapperList;        public static void Set<T>(T instance)        {            if (ServiceWrapper<T>.instance != null)            {                throw new Exception("An instance of this service class has already been set!");            }            ServiceWrapper<T>.instance = instance;            if (serviceWrapperList == null)            {                serviceWrapperList = new List<IServiceWrapper>();            }            serviceWrapperList.Add(new ServiceWrapper<T>());        }        public static T Get<T>()        {            return ServiceWrapper<T>.instance;        }        public static bool IsSet<T>()        {            return ServiceWrapper<T>.instance != null;        }        // Resets references to all services back to null so that they can go out of scope and        // be subjected to garbage collection.        // * Services that reference each other will be garbage collected.        // * AssetBundles should be manually unloaded by an asset manager.        // * GameObjects will be destroyed by the next level load done by the caller.        // * Any application statics should be reset by the caller as well.        // * If there are any unmanaged objects, those need to be released by the caller, too.        public static void ResetAll()        {            if (serviceWrapperList == null)            {                return;            }            // Unset in the reverse order in which services were set.  Probably doesn't matter.            for (int i = serviceWrapperList.Count - 1; i >= 0; i--)            {                serviceWrapperList[i].Unset();            }            serviceWrapperList = null;        }    }    internal class ServiceWrapper<T> : IServiceWrapper    {#if SERVER        [ThreadStatic]#endif        public static T instance = default(T);        public void Unset()        {            ServiceWrapper<T>.instance = default(T);        }    }    internal interface IServiceWrapper    {        void Unset();    }}


具体使用:
void Start () {        Debug.Log("MyCube Start");        //注册事件         Service.Get<EventManager>().RegisterObserver(this, EventId.event1,                EventPriority.Default);         Service.Get<EventManager>().RegisterObserver(this, EventId.event2,                 EventPriority.Default);}


发送事件:
Service.Get<EventManager>().SendEvent(EventId.event1, null);

发送事件后会根据优先级调用注册当前EventId的那个游戏体,  继而执行 相应的OnEvent()
例如给myCube分别注册事件1 和 事件2  mySphere只注册事件1

(如果在OnEvent当中返回的是Eaten)则不会继续向下一个注册改事件的游戏体传递这个事件)





0 0
原创粉丝点击