12 第1页 | 共2 页下一页
返回列表 发新帖
查看: 12349|回复: 16
打印 上一主题 下一主题

[教程] Unity中的事件编程1

[复制链接]

21

主题

7

听众

651

积分

初级设计师

Rank: 3Rank: 3

纳金币
0
精华
3

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

跳转到指定楼层
楼主
发表于 2013-4-15 22:44:37 |只看该作者 |倒序浏览
pstatus"> 本帖最后由 艾西格亚 于 2013-4-16 23:09 编辑

                                                                                unity3d事件编程
      相信大家对Unity3D中的NGUI插件不会陌生吧,但很少有人认真的看过里面的代码。也确实,看那些代码需要相当的毅力的,但是不看的话,就永远也别想用好NGUI,这并不是危言耸听。我接下来要讲述的事件编程将要从NGUI中的一个非常有用的NGUI脚本开始:

        大家打开Unity,导入NGUI包后,打开一个名为UIEventListener.cs的脚本,如下:


using UnityEngine;

[AddComponentMenu("NGUI/Internal/Event Listener")]
public class UIEventListener : MonoBehaviour
{
        public delegate void VoidDelegate (GameObject go);
        public delegate void BoolDelegate (GameObject go, bool state);
        public delegate void FloatDelegate (GameObject go, float delta);
        public delegate void VectorDelegate (GameObject go, Vector2 delta);
        public delegate void StringDelegate (GameObject go, string text);
        public delegate void ObjectDelegate (GameObject go, GameObject draggedObject);
        public delegate void KeyCodeDelegate (GameObject go, KeyCode key);

        public object parameter;

        public VoidDelegate onSubmit;
        public VoidDelegate onClick;
        public VoidDelegate onDoubleClick;
        public BoolDelegate onHover;
        public BoolDelegate onPress;
        public BoolDelegate onSelect;
        public FloatDelegate onScroll;
        public VectorDelegate onDrag;
        public ObjectDelegate onDrop;
        public StringDelegate onInput;
        public KeyCodeDelegate onKey;

        void OnSubmit ()                                { if (onSubmit != null) onSubmit(gameObject); }
        void OnClick ()                                        { if (onClick != null) onClick(gameObject); }
        void OnDoubleClick ()                        { if (onDoubleClick != null) onDoubleClick(gameObject); }
        void OnHover (bool isOver)                { if (onHover != null) onHover(gameObject, isOver); }
        void OnPress (bool isPressed)        { if (onPress != null) onPress(gameObject, isPressed); }
        void OnSelect (bool selected)        { if (onSelect != null) onSelect(gameObject, selected); }
        void OnScroll (float delta)                { if (onScroll != null) onScroll(gameObject, delta); }
        void OnDrag (Vector2 delta)                { if (onDrag != null) onDrag(gameObject, delta); }
        void OnDrop (GameObject go)                { if (onDrop != null) onDrop(gameObject, go); }
        void OnInput (string text)                { if (onInput != null) onInput(gameObject, text); }
        void OnKey (KeyCode key)                { if (onKey != null) onKey(gameObject, key); }

        static public UIEventListener Get (GameObject go)
        {
                UIEventListener listener = go.GetComponent<UIEventListener>();
                if (listener == null) listener = go.AddComponent<UIEventListener>();
                return listener;
        }
}


        如果大家对C#中的事件发布与事件订阅很熟的话,看懂以上代码是轻而易举的事。这里我为对这方面并不熟的朋友唠叨几句:所谓事件的发布者,即为事件的侦听对象,当某个事件发生之后,这个侦听对象就会马上将此事件发送到各个订阅者手上。事件的订阅者即为订阅某个事件的对象,同一个事件可以被多个订阅者所订阅。事件的订阅对象必然会在事件作出相应的动作,否则没必要多此一举。例如:当我们按下某个UI界面的按钮时,一般界面会发生相应的界面,比如谷歌搜索引擎。此时,按钮就相当于事件的发布者,搜索界面的控制程序就相当于事件的订阅对象,针对按钮发布的事件,获取到相应的数据,并将其填充到搜索界面。
        我们可以利用这个脚本中的Get函数来动态的添加事件了。 接下来很快就会看到此种编程的好处了!

        我们打开NGUI中的第7个粒子:Scroll View(Panel)。新建一个Manager的空的GameObject,然后新建一个脚本TestEvent.cs,代码如下:


using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;

public class TestUIEvent : MonoBehaviour {

    public GameObject uiGrid;//所有item的父容器

    private List<Transform> items;//存储所有items的线性表

        // Use this for initialization
        void Start () {

            if(uiGrid == null)//检查父容器是否存在

            {
               Debug.LogError("The uiGide is not exist!");
                return;
            }



            FillItems();//将父容器下的所有子物体添加到items容器中。
        }

    private void FillItems()
    {
        if(items == null)
        {
            items = new List<Transform>(); //实例化此集合
        }

        Transform tr = uiGrid.transform;//获得此父容器的transform
        int count = tr.childCount;//获得此父容器下的子物体数量,便于后面通过transform.GetChild(int index)函数遍历各个子物体的Transform


        if(count == 0)//如果子物体数量为0,就不需要进行下去了。
        {
            Debug.Log("The uiGrid'child count is zero! ");
            return;
        }

        for (int i = 0; i < count; i++)
        {
            items.Add(tr.GetChild(i));//添加各个子物体到items线性表中

        }

        foreach (Transform tm in items)
        {
            UIEventListener listener = null;
            listener = tm.gameObject.GetComponent<UIEventListener>();

            if(listener == null)
            {
                listener = UIEventListener.Get(tm.gameObject);//为各个item动态添加UIEventListener脚本
                listener.onClick += new UIEventListener.VoidDelegate(__ItemOnClickHandler);//订阅各个Item上的OnClick事件

            }

        }
    }

    private void __ItemOnClickHandler(GameObject go) //处理item被单击后的事件。
    {
        Debug.Log("The item name is : "+ go.name +" is onClick!");//简单的打印一下item的名字
    }
}


如图所示,将图中的UIGrid拖拽到TestEvent脚本上的uiGrid选项上:

为此,我特意将Item增加到20个。
好了,我们运行一下吧,结果如下:


UIEventListener脚本已经添加上去了,控制台输出结果如下:
file:///C:/Users/wyb314/AppData/Local/youdao/ynote/images/3FFB8C3DDF374D71BE740EB8F05CBA00/clipboard.png
3.png

试验非常成功,item上的OnClick事件的处理工作很好的转移到__ItemOnClickHandler方法上。这样我们就可以省去大量的绑定脚本的工作。我们可以更有远见的想象一下,加入一个视图比较复杂,我之前做了一个东西的,截图如下:
4.png

这个UI中需要处理的事件至少有4个,而且还会在下面动态生成展现渲染对象,并对其填充数据。这样一来,用绑脚本的方式即使解决了问题,那也是非常稀烂的解法。我是这样处理的,用一个类来控制这个窗口,将这些需要发布事件的控件动态添加UIEventListener脚本,然后在这个类中用不同的回调函数来处理这些事件。事后证明,这种方法是非常有效的,虽然还有待改进。这样一来,我们就省去了很多很多不必要的帮脚本的麻烦。
        我们可以试验一下,尝试着为一个复杂的视图的各个子控件添加不同的事件,然后分别用不同的回调函数来处理。下一篇,我将深入一下这方面的讲解,我想这些东西多少是大家需要的,希望大家多多回复,支持一下我的工作呀!




分享到: QQ好友和群QQ好友和群 腾讯微博腾讯微博 腾讯朋友腾讯朋友 微信微信
转播转播0 分享淘帖0 收藏收藏1 支持支持0 反对反对0
回复

使用道具 举报

2722

主题

42

听众

3万

积分

资深设计师

Rank: 7Rank: 7Rank: 7

纳金币
38268
精华
111

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

沙发
发表于 2013-4-15 22:59:12 |只看该作者
支持楼主的文章,很好的资料分享,收藏了
回复

使用道具 举报

0

主题

1

听众

654

积分

初级设计师

Rank: 3Rank: 3

纳金币
134
精华
0

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

板凳
发表于 2013-4-16 08:09:30 |只看该作者

看上去和可视化编程的工具很像,也是节点的,不错哦
回复

使用道具 举报

2

主题

9

听众

6387

积分

高级设计师

Rank: 6Rank: 6

纳金币
881
精华
0

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

地板
发表于 2013-4-16 17:45:46 |只看该作者
感谢楼主的分享,强啊
回复

使用道具 举报

0

主题

1

听众

7

积分

设计初学者

Rank: 1

纳金币
4
精华
0

活跃会员 灌水之王

5#
发表于 2013-4-17 08:37:30 |只看该作者
太犀利,谢谢奉献~~~~~~~~~~~~
回复

使用道具 举报

4

主题

2

听众

604

积分

初级设计师

Rank: 3Rank: 3

纳金币
14
精华
0

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

6#
发表于 2013-4-18 12:27:34 |只看该作者
NGUI与游戏的整合!Good!
回复

使用道具 举报

11

主题

9

听众

4038

积分

中级设计师

Rank: 5Rank: 5

纳金币
25
精华
0

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

7#
发表于 2013-4-21 09:16:40 |只看该作者
kankan zhege kankan
回复

使用道具 举报

12

主题

1

听众

609

积分

初级设计师

Rank: 3Rank: 3

纳金币
309
精华
0

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

8#
发表于 2013-4-24 08:52:25 |只看该作者
谢楼主分享
回复

使用道具 举报

10

主题

2

听众

1545

积分

助理设计师

Rank: 4

纳金币
79
精华
0

活跃会员

9#
发表于 2013-4-26 15:53:17 |只看该作者
很不错的想法
回复

使用道具 举报

Sora    

0

主题

1

听众

86

积分

设计初学者

Rank: 1

纳金币
4
精华
0

活跃会员 灌水之王

10#
发表于 2013-4-28 08:53:53 |只看该作者
很不錯的學習思路
回复

使用道具 举报

12 第1页 | 共2 页下一页
返回列表 发新帖
您需要登录后才可以回帖 登录 | 立即注册

手机版|纳金网 ( 闽ICP备2021016425号-2/3

GMT+8, 2024-12-1 12:43 , Processed in 0.101087 second(s), 35 queries .

Powered by Discuz!-创意设计 X2.5

© 2008-2019 Narkii Inc.

回顶部