Unity3D_2019:在运行时添加事件触发器

Alp*_*Joe 1 c# unity-game-engine

在 Unity3D 2017 版中,您可以EventTriggers通过执行以下操作一次添加多个:

for (int i = 0; i < 20; i++)
{
    EventTrigger.Entry pDown = new EventTrigger.Entry();
    pDown.eventID = EventTriggerType.PointerDown;
    pDown.callback.AddListener((eventdata) => { InventorySlotCopy(); });
    slots[i].GetComponent<EventTrigger>().triggers.Add(pDown);

    EventTrigger.Entry pUp = new EventTrigger.Entry();
    pUp.eventID = EventTriggerType.PointerUp;
    pUp.callback.AddListener((eventdata) => { InventorySlotInsert(); });
    slots[i].GetComponent<EventTrigger>().triggers.Add(pUp);
}
Run Code Online (Sandbox Code Playgroud)

whereslots只是一个arrayof GameObjects,每个都有一个Image和一个EventTrigger附加到它。

然而,使用如以上在Unity3D版2019所导致添加这些相同的代码EventTriggers而不是在分配functionsListener

在此处输入图片说明

在 Unity2019 中是如何做到的?

der*_*ugo 6

首先:

您将不会在 Inspector 中看到添加的侦听器!

在 Inspector 中,您只能看到永久侦听器,而不是在运行时添加的侦听器!这些基本上都是UnityEvent<BaseEventData>如此,请参阅手册:UnityEvents

当 aUnityEvent添加到 a 时,MonoBehaviour它会出现在 Inspector 中,并且可以添加持久回调

添加永久侦听器的唯一方法是通过 Inspector 或自定义 EditorScript!但这无论如何都不是你想要做的。


我会稍微修改您的脚本以使其更安全。我只是在方法被调用时记录一些消息,以表明它们被调用了。

public class Example : MonoBehaviour
{
    // Rather make these directly of type EventTrigger
    // So you don't have to use GetComponent later and can be sure that these array only receives
    // objects that actually have that Component attached!
    public EventTrigger[] slots;

    private void Start()
    {
        // Instead of a hardcoded index either iterate using slots.Length
        // or simply directly foreach
        foreach (var slot in slots)
        {
            var pDown = new EventTrigger.Entry
            {
                eventID = EventTriggerType.PointerDown
            };

            pDown.callback.AddListener(eventData => { InventorySlotCopy(); });
            slot.triggers.Add(pDown);

            var pUp = new EventTrigger.Entry
            {
                eventID = EventTriggerType.PointerUp
            };

            pUp.callback.AddListener(eventData => { InventorySlotInsert(); });
            slot.triggers.Add(pUp);
        }
    }

    private void InventorySlotCopy()
    {
        Debug.Log(nameof(InventorySlotCopy));
    }

    private void InventorySlotInsert()
    {
        Debug.Log(nameof(InventorySlotInsert));
    }
}
Run Code Online (Sandbox Code Playgroud)

其余的取决于您的设置。我们不知道您slots是什么对象,但基本上有两(三)个选项:

选项 1 - 用户界面

如果这些插槽对象是诸如或 之类的UI元素。CanvasImageText

这似乎是您的具体情况。

  1. 确保EventSystem场景中有礼物。

    通常在创建第一个Canvas.

    如果没有现在通过Hierachy Viewright clickUI→创建它EventSystem

  2. 确保您在插槽的 UI 组件上RayCast Target 启用了该选项。

结果:

在此处输入图片说明


选项 2 - 3D 对象(选项 3 - 带有 2D 碰撞器的 3D 对象)

只是为其他用户添加这个。

如果这些对象不是UI 元素而是 3D 对象,请确保

  1. 再次你需要EventSystem像以前一样

  2. 这些槽Collider组件连接于相同GameObjectEvenTrigger组件被附接到或任何其子的(它可以嵌套)。

  3. Camera需要PhysicsRaycaster附加的组件。确保此处eventMask包含放置插槽对象的层。(对于使用 2D Colliders 的选项 3,请使用Physics2DRaycaster

结果:

在此处输入图片说明


如您所见,这些方法在 Inspector 中将不可见(由于前面提到的原因),但添加的侦听器方法仍会被调用。