Unity快速入门之三 脚本与事件

这篇Unity教程介绍了如何创建和挂载C#脚本,以及Unity的内置事件系统,包括按钮(Button)的OnClick事件和文本(Text)的Trigger事件。文章还深入探讨了自定义事件系统的实现,包括EventManager类的使用,展示了不同类型的事件处理方式,如UnityEvent、Delegate、Func和Action。此外,教程还提供了完整的代码示例,帮助读者理解和应用Unity的事件系统。
摘要由CSDN通过智能技术生成

Unity快速入门之一 3D基础概念、Camera、Canvas RenderMode的几种方式对比_翕翕堂

Unity快速入门之二 GUI Transform 详解_翕翕堂

Unity快速入门之三 脚本与事件_翕翕堂

Unity快速入门之四 - Unity模型动画相关_翕翕堂-CSDN博客

资源管理待定……

……

这一篇主要是从代码了,代码内容是纯示例内容,可以有更多更好的思路扩展。

本篇幅会比较长,涉及到比较多的内容,请坐好准备发车~~~~

前置准备就需要自己准备好了:

1、准备 visual studio 2017 IDE。

2、安装 vs for unity 插件。

3、C#语法基础或其他语言基础。


目录

C# Script(脚本)

脚本创建

挂载脚本

前置场景与知识准备

Unity内置事件

Unity按钮(Button)点击(OnClick)事件

文本(Text)触发(Trigger)事件

自定义(Custom)触发(Trigger)事件

自定义事件系统

铺垫

EventManagerUnity(UnityEvent && UnityAction)

EventManagerDelegate

EventManagerFunc

EventManagerAction

 EventManagerFunc

事件系统总结


C# Script(脚本)

脚本创建

Project视图下,Assets及其子目录,右键菜单->Create->C# Script:

创建C#脚本方式

建一个Script文件夹,创建一个C#脚本,默认脚本名字 New Behaviour Script,点击脚本,可以在 Inspector中可以显示脚本内容:

第一个默认脚本

挂载脚本

将创建的脚本当成组件挂载到3D对象身上

Hierarchy视图中选中一个3D对象,在其Inspector视图中,最下方点击 Add Componet 按钮,输入框中搜索刚才创建的脚本 NewBehaviourScript,就可以看到它了,点击挂在到这个对象上:

脚本被挂载了

先用 vs2017打开这个脚本,双击上方图片中黄色位置即可(需要配置好环境,不展开了):

vs2017下脚本

前置场景与知识准备

由于按钮是最通用的控件,从它开始切入。首先创建一个基础场景:

  • 按钮控件:button event
  • 文本控件:text event
  • 文本控件:custom trigger
  • 3D Cube:Cube
一个按钮、两个文本、一个cube

创建一个脚本 ButtonEvent,并放到 button event控件 上,先介绍几个脚本的基本内容:

MonoBehaviour:Unity对象的基础类,里面拥有很完整的生命周期,继承于这个类的脚本都可以当成组件挂载到具体的对象身上。

void Start():首次加载以及对象再次激活的时候会被调用,这次我们只要用到它就好了。

gameObject:此脚本组件说挂载的对象,由于我们要使用Button及其点击事件,Button也是一个独立组件,要由它来获取。

Unity内置事件

Unity按钮(Button)点击(OnClick)事件

流程上:

  • 创建点击处理函数
  • 找到按钮
  • 绑定处理函数到按钮

按钮点击函数上代码实现方式,常见的四种:

  • 成员函数
  • 匿名委托
  • 实例委托
  • lambda

这些都是基于C#语法的,语法规则就不做展开了。

下面开始说 Button怎么绑定点击响应事件,首先,保留脚本最简形式:

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

public class ButtonEvent : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {

    }
}

增加一个响应我们点击事件的成员函数作为处理函数:

public class ButtonEvent : MonoBehaviour
{
    void Start()...

    public void OnClickFunction00()
    {
        Debug.Log("AddListener - 委托成员函数 - OnClickFunction00");
    }
}

在Start中找到我们要的按钮,并将处理函数绑定到按钮上:

// 使用控件需要添加的命名空间
using UnityEngine.UI;

public class ButtonEvent : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        // AddListener - 成员函数 - OnClickFunction
        gameObject.GetComponent<Button>().onClick.AddListener(OnClickFunction00);
    }

    public void OnClickFunction00()...
}

由于使用了Butoon,这个属于 UnityEngine.UI 之下,所以开头要使用 using UnityEngine.UI

获取组件通过 gameObject.GetComponent<T>() 接口,我们这用的Button,所以是gameObject.GetComponent<Button>() ,下一步要绑定处理函数到按钮上,上面已经写出来了,就是  onClick.AddListener(OnClickFunction00),这是怎么来的,可以翻官网或度娘:Unity - Manual: UnityEventshttps://docs.unity3d.com/Manual/UnityEvents.html

也可以看下它的实现,我们点开Button看看:

Unity UI Button

可以看到Unity的UI Button,有一个OnClick,来自于ButtonClickedEvent,而它又来自于UnityEvent,另外Button继承于几个xxxHandler 接口

我们继续点开UnityEvent看看:

UnityEvent

看到 Reflection、MethodInfo、Invoke,大概就知道,这东西是靠反射来实现的,这里就不继续往 UnityEventBase展开了,但是可以给没接触过反射的朋友大概说下,反射(Reflection)就是通过拿到目标类及其类下所有的变量、函数等信息,做额外存储,在运行时可以通个这些额外存储的信息以及类的实例对象进行调用,但是需要占用额外内存,性能也比较低。

好了,我们继续。

它的目标函数怎么绑定的,这个很明显:public void AddListener(UnityAction call);

那么UnityAction是什么玩意儿,点进去看看:public delegate void UnityAction();

UnityAction

一个委托(Delegate),类似于C++的函数指针形式,但是使用的时候实际上是对象。

掌握了这些信息,我们可以继续拓展我们的事件了。(对于上面 反射、委托不懂想要深究的,可以找其他资料进行了解)

首先看下上面的结果:

Debug窗口信息

没毛病,点击按钮,确实输出了我们需要的消息。既然 UnityAction 是个 delegate,那么我们应该可以直接使用委托匿名函数来作为处理函数。

{
    // Start is called before the first frame update
    void Start()
    {
        ...

        // AddListener - 委托匿名函数 - delegate
        gameObject.GetComponent<Button>().onClick.AddListener(delegate
        {
            Debug.Log("AddListener - 委托匿名函数 - delegate");
        });
    }

    public void OnClickFunction00()...
}

 也可以使用委托实例,这里显示的调用了 UnityAction,需要增加 using UnityEngine.Events

// 使用UnityAction需要增加这个
using UnityEngine.Events

public class ButtonEvent : MonoBehaviour{
    // Start is called before the first frame update
    void Start()
    {
        ...

        // AddListener - 委托实例 - OnClickFunction01
        gameObject.GetComponent<Button>().onClick.AddListener(
            new UnityAction(OnClickFunction01)
        );
    }

    public void OnClickFunction00()...

    public void OnClickFunction01()
    {
        Debug.Log("实例委托 - OnClickFunction02");
    }
}

委托lambda: 

{
    // Start is called before the first frame update
    void Start()
    {
        ...

        // AddListener - 委托lambda表达式 - lambda
        gameObject.GetComponent<Button>().onClick.AddListener(
            () => Debug.Log("lambda表达式委托 - lambda")
        );
    }

    public void OnClickFunction00()...
}

 由于UnityAction是委托,所以可以不调用AddListener,直接使用多路广播,最后一次性绑定:

{
    //创建UnityAction成员变量
    public UnityAction m_untiyAction;

    // Start is called before the first frame update
    void Start()
    {
        // 多路广播,委托函数
        m_untiyAction += OnClickFunction01;

        // 委托匿名函数
        m_untiyAction += delegate
        {
            Debug.Log("多路广播 - 匿名函数委托 - delegate");
        };

        // 委托实例 - OnClickFunction01
        m_untiyAction += new UnityAction(OnClickFunction01);

        // 委托lambda表达式
        m_untiyAction += () => { Debug.Log("多路广播 - lambda表达式委托 - lambda"); };

        // AddListener - UnityAction - delegate
        // 将UnityAction绑定到AddListener
        gameObject.GetComponent<Button>().onClick.AddListener(m_untiyAction);
    }

    public void OnClickFunction00()...
}

 放个完整的ButtonEvent代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Events;

public class ButtonEvent : MonoBehaviour
{
    //https://docs.unity3d.com/Manual/UnityEvents.html
    public UnityAction m_untiyAction;

    // Start is called before the first frame update
    void Start()
    {
        // AddListener - 成员函数 - OnClickFunction
        gameObject.GetComponent<Button>().onClick.AddListener(OnClickFunction00);

        // AddListener - 委托匿名函数 - delegate
        gameObject.GetComponent<Button>().onClick.AddListener(delegate
        {
            Debug.Log("AddListener - 委托匿名函数 - delegate");
        });

        // AddListener - 委托实例 - OnClickFunction01
        gameObject.GetComponent<Button>().onClick.AddListener(new UnityAction(OnClickFunction01));

        // AddListener - 委托lambda表达式 - lambda
        gameObject.GetComponent<Button>().onClick.AddListener(
            () => Debug.Log("lambda表达式委托 - lambda")
        );

        // 多路广播,委托函数
        m_untiyAction += OnClickFunction01;

        // 委托匿名函数
        m_untiyAction += delegate
        {
            Debug.Log("多路广播 - 匿名函数委托 - delegate");
        };

        // 委托实例 - OnClickFunction01
        m_untiyAction += new UnityAction(OnClickFunction01);

        // 委托lambda表达式
        m_untiyAction += () => { Debug.Log("多路广播 - lambda表达式委托 - lambda"); };

        // AddListener - UnityAction - delegate
        gameObject.GetComponent<Button>().onClick.AddListener(m_untiyAction);
    }

 
  • 6
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值