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;
    }
}
原文地址:https://www.cnblogs.com/jiangshuai52511/p/5439110.html