Unity3D 自定义事件(事件侦听与事件触发)
先来看下效果图,图中点击 Cube(EventDispatcher),Sphere(EventListener)以及 Capsule(EventListener)会做出相应的变化,例子中的对象相互之间没有引用,也没有父子关系。
Demo 事件触发者(EventDispatcher)CubeObject.cs,挂载在 Cube 对象上
using UnityEngine; using System.Collections; public class CubeObject : MonoBehaviour { void Update() { if (Input.GetMouseButtonDown (0)) { Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); RaycastHit raycastHit = new RaycastHit(); if(Physics.Raycast(ray, out raycastHit)) { if(raycastHit.collider.gameObject.name == "Cube") { // 触发事件 ObjectEventDispatcher.dispatcher.dispatchEvent(new UEvent(EventTypeName.CUBE_CLICK, "cube"), this); } } } } }
Demo 事件侦听者(EventListener)CapsuleObject.cs,挂载在 Capsule 对象上
using UnityEngine; using System.Collections; public class CapsuleObject : MonoBehaviour { private float angle; private float targetAngle; private float currentVelocity; void Awake() { // 添加事件侦听 ObjectEventDispatcher.dispatcher.addEventListener (EventTypeName.CUBE_CLICK, OnClickHandler); } /// <summary> /// 事件回调函数 /// </summary> /// <param name="uEvent">U event.</param> private void OnClickHandler(UEvent uEvent) { this.targetAngle = this.targetAngle == 90f ? 0f : 90f; this.StopCoroutine (this.RotationOperater ()); this.StartCoroutine (this.RotationOperater()); } IEnumerator RotationOperater() { while (this.angle != this.targetAngle) { this.angle = Mathf.SmoothDampAngle (this.angle, this.targetAngle, ref currentVelocity, 0.5f); this.transform.rotation = Quaternion.AngleAxis(this.angle, Vector3.forward); if(Mathf.Abs(this.angle - this.targetAngle) <= 1) this.angle = this.targetAngle; yield return null; } } }
Demo 事件侦听者(EventListener)SphereObject.cs,挂载在 Sphere 对象上
using UnityEngine; using System.Collections; public class SphereObject : MonoBehaviour { private float position; private float targetPosition; private float currentVelocity; void Awake() { // 添加事件侦听 ObjectEventDispatcher.dispatcher.addEventListener (EventTypeName.CUBE_CLICK, OnClickHandler); } /// <summary> /// 事件回调函数 /// </summary> /// <param name="uEvent">U event.</param> private void OnClickHandler(UEvent uEvent) { this.targetPosition = this.targetPosition == 2f ? -2f : 2f; this.StopCoroutine (this.PositionOperater ()); this.StartCoroutine (this.PositionOperater()); } IEnumerator PositionOperater() { while (this.position != this.targetPosition) { this.position = Mathf.SmoothDamp (this.position, this.targetPosition, ref currentVelocity, 0.5f); this.transform.localPosition = new Vector3(this.transform.localPosition.x, this.position, this.transform.localPosition.z); if(Mathf.Abs(this.position - this.targetPosition) <= 0.1f) this.position = this.targetPosition; yield return null; } } }
Demo 辅助类 EventTypeName.cs
using UnityEngine; using System.Collections; public class EventTypeName { public const string CUBE_CLICK = "cube_click"; }
Demo 辅助类 ObjectEventDispatcher.cs
using UnityEngine; using System.Collections; public class ObjectEventDispatcher { public static readonly UEventDispatcher dispatcher = new UEventDispatcher(); }
事件触发器 UEventDispatcher.cs
using System; using System.Collections.Generic; public class UEventDispatcher { protected Dictionary<string, UEventListener> eventListenerDict; public UEventDispatcher() { this.eventListenerDict = new Dictionary<string, UEventListener>(); } /// <summary> /// 侦听事件 /// </summary> /// <param name="eventType">事件类别</param> /// <param name="callback">回调函数</param> public void addEventListener(string eventType, UEventListener.EventListenerDelegate callback) { if (!this.eventListenerDict.ContainsKey(eventType)) { this.eventListenerDict.Add(eventType, new UEventListener()); } this.eventListenerDict[eventType].OnEvent += callback; } /// <summary> /// 移除事件 /// </summary> /// <param name="eventType">事件类别</param> /// <param name="callback">回调函数</param> public void removeEventListener(string eventType, UEventListener.EventListenerDelegate callback) { if (this.eventListenerDict.ContainsKey(eventType)) { this.eventListenerDict[eventType].OnEvent -= callback; } } /// <summary> /// 发送事件 /// </summary> /// <param name="evt">Evt.</param> /// <param name="gameObject">Game object.</param> public void dispatchEvent(UEvent evt, object gameObject) { UEventListener eventListener = eventListenerDict[evt.eventType]; if (eventListener == null) return; evt.target = gameObject; eventListener.Excute(evt); } /// <summary> /// 是否存在事件 /// </summary> /// <returns><c>true</c>, if listener was hased, <c>false</c> otherwise.</returns> /// <param name="eventType">Event type.</param> public bool hasListener(string eventType) { return this.eventListenerDict.ContainsKey(eventType); } }
事件侦听器 UEventListener.cs
using System; public class UEventListener { public UEventListener() { } public delegate void EventListenerDelegate(UEvent evt); public event EventListenerDelegate OnEvent; public void Excute(UEvent evt) { if (OnEvent != null) { this.OnEvent(evt); } } }
事件参数 UEvent.cs
using System; public class UEvent { /// <summary> /// 事件类别 /// </summary> public string eventType; /// <summary> /// 参数 /// </summary> public object eventParams; /// <summary> /// 事件抛出者 /// </summary> public object target; public UEvent(string eventType, object eventParams = null) { this.eventType = eventType; this.eventParams = eventParams; } }