【Unity】Unity开发进阶(六)UnityEvent使用与源码解析

42 篇文章 11 订阅
34 篇文章 18 订阅


UnityEvent

UnityEvent是Unity提供的用于处理事件的类,方便我们自定义事件。为了便于参数传递,Unity默认为我们提供了多个事件类,通过泛型不同实现事件响应参数不同。
在这里插入图片描述

如何使用

对于如何使用UnityEvent,官方文档给出了简单的使用案例,我们以一个泛型的版本为例。

UnityEvent代表使用此事件时可以添加一种类型,在调用Invoke方法时可以将此类型作为参数传入,事件响应端会接收到这个参数,以获取事件上下文。

如下图案例,我们自制的MyIntEvent继承UnityEvent,当事件触发调用Invoke方法时将int值5传入,此时Ping方法就会接收到事件响应时传入的5。

下面为Unity官方文档中提供的代码。
在这里插入图片描述

using UnityEngine;
using UnityEngine.Events;

[System.Serializable]
public class MyIntEvent : UnityEvent<int>
{
}

public class ExampleClass : MonoBehaviour
{
    public MyIntEvent m_MyEvent;

    void Start()
    {
        if (m_MyEvent == null)
            m_MyEvent = new MyIntEvent();

        m_MyEvent.AddListener(Ping);
    }

    void Update()
    {
        if (Input.anyKeyDown && m_MyEvent != null)
        {
            m_MyEvent.Invoke(5);
        }
    }

    void Ping(int i)
    {
        Debug.Log("Ping" + i);
    }
}

何时使用

比如,当我们想要在屏幕上做多个按钮时,每个按钮的触发要有相应的区分,我们可以利用一个for循环来批量添加事件,并在事件触发时传入相应的 i(index索引),并使用同一个事件触发响应器。每个按钮被点击都会触发这个相同的事件响应器,响应器可以接收到参数index,以此来判断是哪个按钮被点击了。

实现原理

不带泛型的UnityEvent使用无参数方式调用Invoke方法。

以下为UnityEvent代码:

using System.Reflection;
using UnityEngine.Scripting;

namespace UnityEngine.Events
{
    //
    // 摘要:
    //     A zero argument persistent callback that can be saved with the Scene.
    public class UnityEvent : UnityEventBase
    {
        //
        // 摘要:
        //     Constructor.
        [RequiredByNativeCode]
        public UnityEvent();

        //
        // 摘要:
        //     Add a non persistent listener to the UnityEvent.
        //
        // 参数:
        //   call:
        //     Callback function.
        public void AddListener(UnityAction call);
        //
        // 摘要:
        //     Invoke all registered callbacks (runtime and persistent).
        public void Invoke();
        //
        // 摘要:
        //     Remove a non persistent listener from the UnityEvent.
        //
        // 参数:
        //   call:
        //     Callback function.
        public void RemoveListener(UnityAction call);
        protected override MethodInfo FindMethod_Impl(string name, object targetObj);
    }
}

带泛型的UnityEvent将泛型作为参数传递给Invoke方法。

以下为UnityEvent代码:

using System.Reflection;
using UnityEngine.Scripting;

namespace UnityEngine.Events
{
    //
    // 摘要:
    //     One argument version of UnityEvent.
    public abstract class UnityEvent<T0> : UnityEventBase
    {
        [RequiredByNativeCode]
        public UnityEvent();

        public void AddListener(UnityAction<T0> call);
        public void Invoke(T0 arg0);
        public void RemoveListener(UnityAction<T0> call);
        protected override MethodInfo FindMethod_Impl(string name, object targetObj);
    }
}

多个泛型的情况以此类推。

在AddListener和RemoveListener中都传入了参数UnityAction call,看这个名字就像个回调函数,我们看一下代码:

以下为UnityAction代码:

namespace UnityEngine.Events
{
    //
    // 摘要:
    //     Zero argument delegate used by UnityEvents.
    public delegate void UnityAction();
}

果然,UnityAction其实就是个委托方法。

看过了UnityEvent和UnityAction,那么UnityEvent的基类都做了些什么呢?

以下为UnityEventBase代码:

using System;
using System.Reflection;
using UnityEngine.Scripting;

namespace UnityEngine.Events
{
    //
    // 摘要:
    //     Abstract base class for UnityEvents.
    [UsedByNativeCode]
    public abstract class UnityEventBase : ISerializationCallbackReceiver
    {
        protected UnityEventBase();

        //
        // 摘要:
        //     Given an object, function name, and a list of argument types; find the method
        //     that matches.
        //
        // 参数:
        //   obj:
        //     Object to search for the method.
        //
        //   functionName:
        //     Function name to search for.
        //
        //   argumentTypes:
        //     Argument types for the function.
        public static MethodInfo GetValidMethodInfo(object obj, string functionName, Type[] argumentTypes);
        //
        // 摘要:
        //     Get the number of registered persistent listeners.
        public int GetPersistentEventCount();
        //
        // 摘要:
        //     Get the target method name of the listener at index index.
        //
        // 参数:
        //   index:
        //     Index of the listener to query.
        public string GetPersistentMethodName(int index);
        //
        // 摘要:
        //     Get the target component of the listener at index index.
        //
        // 参数:
        //   index:
        //     Index of the listener to query.
        public Object GetPersistentTarget(int index);
        //
        // 摘要:
        //     Remove all non-persisent (ie created from script) listeners from the event.
        public void RemoveAllListeners();
        //
        // 摘要:
        //     Modify the execution state of a persistent listener.
        //
        // 参数:
        //   index:
        //     Index of the listener to query.
        //
        //   state:
        //     State to set.
        public void SetPersistentListenerState(int index, UnityEventCallState state);
        public override string ToString();
        protected void AddListener(object targetObj, MethodInfo method);
        protected abstract MethodInfo FindMethod_Impl(string name, object targetObj);
        protected void Invoke(object[] parameters);
        protected void RegisterPersistentListener(int index, object targetObj, MethodInfo method);
        protected void RemoveListener(object targetObj, MethodInfo method);
        protected bool ValidateRegistration(MethodInfo method, object targetObj, PersistentListenerMode mode);
        protected bool ValidateRegistration(MethodInfo method, object targetObj, PersistentListenerMode mode, Type argumentType);
    }
}

以下为ISerializationCallbackReceiver代码:

using UnityEngine.Scripting;

namespace UnityEngine
{
    [RequiredByNativeCode]
    public interface ISerializationCallbackReceiver
    {
        //
        // 摘要:
        //     Implement this method to receive a callback after Unity deserializes your object.
        [RequiredByNativeCode]
        void OnAfterDeserialize();
        //
        // 摘要:
        //     Implement this method to receive a callback before Unity serializes your object.
        [RequiredByNativeCode]
        void OnBeforeSerialize();
    }
}

从UnityEventBase和ISerializationCallbackReceiver的内容可以看出,其实Unity提供的功能并不复杂,只是提供了一些工具方法和一些抽象方法,其最主要的工作还是帮助开发者完成了委托,以提高代码可读性。

总结

UnityEvent其实就是Unity帮我们提前写好的用于处理事件的功能,其作用是减去了自己写委托的过程,且提高了开发的规范性,方便代码整合。


更多内容请查看总目录【Unity】Unity学习笔记目录整理

  • 10
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Unity3D脚本编程与游戏开发源码提供了一种有效的方式来创建令人兴奋的游戏Unity3D是一款功能强大的游戏引擎,它允许开发使用C#或JavaScript等脚本语言来编写游戏逻辑。 Unity3D脚本编程基于组件的设计模式。开发者可以在场景中添加各种组件,并使用脚本来控制它们的行为。例如,可以创建一个脚本来控制玩家角色的移动,另一个脚本来控制敌人的行为。这种模块化的设计使得开发过程更加灵活和可维护。 脚本编程也提供了一种可视化的方式来操纵游戏对象。Unity3D提供了一个强大的编辑器,开发者可以使用脚本来创建自定义的编辑器工具,这使得设计人员可以更轻松地进行游戏开发和调试。脚本编程还可以与其他功能强大的开发工具相结合,如动画和物理引擎,以创建更加逼真和令人印象深刻的游戏体验。 对于游戏开发源码来说,它是一种可供开发者学习和参考的资源。通过研究和了解游戏开发源码开发者可以深入了解游戏开发的各个方面,包括游戏逻辑、资源管理、碰撞检测等。源码还可以帮助开发者提高编程和设计技巧,并为他们提供创建自己游戏的灵感和指导。 总之,Unity3D脚本编程与游戏开发源码提供了一种强大的工具和资源,帮助开发者创建令人兴奋和吸引人的游戏。它们对于游戏开发者来说是宝贵的资产,可以帮助他们实现创意,并创造出独一无二的游戏体验。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值