纳金网

标题: Unity中的事件编程2 [打印本页]

作者: wyb314    时间: 2013-4-16 20:39
标题: Unity中的事件编程2
      上一篇我介绍了从一个NGUI视图中转移基本事件到一个对象中去处理的方法,这次我们还是用同样的方法,将Mono事件也进行转移,这样一来,我们就又可以省去很多有关挂脚本的无谓的操作了。下面是部分代码:

using UnityEngine;
using System.Collections;

#region Mono事件代理

public delegate void MonoEvent();
#endregion

public class UIMonoEventListener : MonoBehaviour
{
    #region 常用Mono事件,还没有全部完成,先写常用的

    /// <summary>
    /// Start事件
    /// </summary>
    public event MonoEvent StartMono;
        void Start () {
            if(StartMono != null)

            {                 StartMono();

            }

        }

    /// <summary>
    /// Update事件
    /// </summary>
    public event MonoEvent UpdateMono;
        void Update () {
            if(UpdateMono != null)

            {                UpdateMono();

            }

        }

    /// <summary>
    /// LateUpdate事件
    /// </summary>
    public event MonoEvent LateUpdateMono;
    void LateUpdate()
    {
        if(LateUpdateMono != null)
        {
            LateUpdateMono();
        }
    }

    /// <summary>
    /// FixedUpdate事件
    /// </summary>
    public event MonoEvent FixedUpdateMono;
    void FixedUpdate()
    {
        if(FixedUpdateMono != null)
        {
            FixedUpdateMono();
        }
    }

    /// <summary>
    /// 当Mono将被销毁时调用
    /// </summary>
    public event MonoEvent OnDestroyMono;
    void OnDestroy()
    {
        if(OnDestroyMono != null)
        {
            OnDestroyMono();
        }

    }

    /// <summary>
    /// 当被激活时执行的事件
    /// </summary>
    public event MonoEvent OnEnableMono;
    void OnEnable()
    {
        if(OnEnableMono != null)
        {
            OnEnableMono();
        }
    }

    /// <summary>
    /// 当此GameObject被禁用时被调用
    /// </summary>
    public event MonoEvent OnDisableMono;
    void OnDisable()
    {
        if(OnDisableMono != null)
        {
            OnDisableMono();
        }
    }
    #endregion


}

我们可以像UIEventListener中的Get方法那样动态的添加事件到GameObject上,但是,有比他更好的通用的方式。而且我还可以将其通用于UIEventListener类中。我们看以下代码:
using System;
using System.Collections;
using System.Collections.Generic;
using Object = UnityEngine.Object;//使用特定命名空间类的别名


public class Listener
{
    #region  为一个Object添加UIMonoEventListener并返回其实例
    public static UIMonoEventListener AddUIMonoEvent(Object o)
    {
        if(o == null)
        {
            return null;
        }

        UIMonoEventListener monoEvent = null;
        monoEvent = SetMonoEvent(o);
        return monoEvent;   
    }

    /// <summary>
    /// 获得UnityEngine.Object上的UIMonoEventListener
    /// </summary>
    /// <param name="o">Unity引擎自己的Object类</param>
    /// <returns></returns>
    private static UIMonoEventListener SetMonoEvent(Object o)
    {

        UIMonoEventListener monoEvent = null;

        monoEvent = GetMonoEvent(o);

        if(monoEvent == null)//分别根据o的类型来为其所在的GameObject动态添加UIMonoEventListener脚本
        {
            if(o.GetType() == typeof(Transform))
            {
                monoEvent = (o as Transform).gameObject.AddComponent<UIMonoEventListener>();
            }

            if(o.GetType() == typeof(GameObject))
            {
                monoEvent = (o as GameObject).AddComponent<UIMonoEventListener>();
            }

            if(o.GetType().IsSubclassOf(typeof(MonoBehaviour)))
            {
                monoEvent = (o as MonoBehaviour).gameObject.AddComponent<UIMonoEventListener>();
            }

            return monoEvent;
        }

        return monoEvent;
    }

    /// <summary>
    /// 获得UnityEngine.Object上的UIMonoEventListener
    /// </summary>
    /// <param name="o"></param>
    /// <returns></returns>
    private static UIMonoEventListener GetMonoEvent(Object o)
    {
        UIMonoEventListener monoEvent = null;

        if(o.GetType() == typeof(Transform))//如果此对象的类型为Transform
        {
            monoEvent = (o as Transform).GetComponent<UIMonoEventListener>();
        }

        if(o.GetType() == typeof(GameObject))
        {
            monoEvent = (o as GameObject).GetComponent<UIMonoEventListener>();
        }

        if(o.GetType().IsSubclassOf(typeof(MonoBehaviour)))
        {
            monoEvent = (o as MonoBehaviour).gameObject.GetComponent<UIMonoEventListener>();
        }

        return monoEvent;
    }
    #endregion


}

这样一来,我们就可以对一个名为A的GameObject添加Mono事件了,比如:
Listener. AddUIMonoEvent( A ).UpdateMono += __onUpdate;然后我们可以写一个__OnUpdate的毁掉函数来处理OnUpdate事件,很显然,此回调函数也是每帧执行一次的。好了,我们可以试验一下了,新建一个场景,里面只有两个Cube与一个主摄像机,然后新建一个测试脚本:TestMonoEvent,将其绑定在主摄像机上:
using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;

public class TestMonoEvent : MonoBehaviour {

    public List<GameObject> cubes;

        // Use this for initialization
        void Start () {

        UnityEngine.Object[] gas = FindObjectsOfType(typeof(BoxCollider));//找到带有BoxCollider的这些个类

        if(gas == null)
        {
            return;
        }

        if(gas.Length == 0)
        {
            return;
        }

        foreach (UnityEngine.Object ob in gas)
        {
            GameObject go = ob as GameObject;

            cubes.Add(go);
        }

        foreach (GameObject go in cubes)
        {
            if (go.name == "Cube1")
            {
                Listener.AddUIMonoEvent(go).UpdateMono += new MonoEvent(TestMonoEvent_UpdateMono);
            }
            else
            {
                Listener.AddUIMonoEvent(go).StartMono += new MonoEvent(TestMonoEvent_StartMono);
            }

        }
    }

    void TestMonoEvent_StartMono()
    {
        Debug.Log("Start is invoke!");
    }

    void TestMonoEvent_UpdateMono()
    {
        Debug.Log("Update is invoke!");
    }
       
}



以上代码非常简单,只是为两个Cube分别添加了UpdateMono事件于StartMono事件,下面我们来运行看看:
1.png
成功了,但是,以上事件类还有几个地方需要改进,比如我们订阅事件时,有时需要知道发布事件的对象的引用,那么我们该怎么修改UIMonoEventLisntener类才能满足此需求呢?我想大家应该很快可以对其做出些修改以满足此需求。好了,再见!





作者: 艾西格亚    时间: 2013-4-16 21:15
很不错的介绍,希望继续分享NGUI更多的教程!
作者: wyb314    时间: 2013-4-16 21:30
恩,一定一定。
作者: hpl123    时间: 2013-4-17 08:59
顶楼主,太好看了~~~~~~~~~~
作者: 我没有过去    时间: 2013-4-17 09:15
感谢楼主的分享
作者: ling    时间: 2013-4-17 12:20

感谢楼主的分享
作者: Sora    时间: 2013-4-28 09:15
好棒的教學呀 !!
作者: 王者再临    时间: 2013-6-2 21:34
顶一个,支持楼主的教程!
作者: herry7x    时间: 2013-6-28 11:11
楼主的教程一直很好
作者: lsermao    时间: 2013-6-28 11:46
专业啊,不错的教程
作者: 狂风大尉    时间: 2013-6-28 15:58
楼主的一系列教程很值得推荐
作者: saviosun    时间: 2013-7-1 10:00
不错的方法。
作者: nianhua2008    时间: 2013-12-28 23:47
很不错,感谢了!




欢迎光临 纳金网 (http://go.narkii.com/club/) Powered by Discuz! X2.5