将参数传递给UnityEvent

5

好的,我有点困惑。我学习了 UnityEvent 和消息系统,参考了这篇 教程。但是我有一个问题,我无法理解。我如何将参数传递给调用函数?

例如(我像教程中一样有一个EventManager):

void OnEnable() {
        EventManager.StartListening ("OnPlayerTeleport", TeleportPlayer);
    }

    void OnDisable() {
        EventManager.StopListening ("OnPlayerTeleport", TeleportPlayer);
    }

    void TeleportPlayer () {
        float yPos = transform.position.y;
        yPos += 20.0f;
        transform.position = new Vector3 (transform.position.x, yPos, transform.position.z);
    }

我有一个触发器:

void Update () {
    if (Input.GetButtonDown ("Teleport")) {
        EventManager.TriggerEvent ("OnPlayerTeleport");
    }
}

但是,如果我想将“height”值传递给函数“TeleportPlayer”怎么办:

void TeleportPlayer (float h) {
    float yPos = transform.position.y;
    yPos += h;
    transform.position = new Vector3 (transform.position.x, yPos, transform.position.z);
}

我该如何做到这一点?
2个回答

2
请使用C#委托/Action代替Unity的UnityEvent,它比Unity的事件更快。我几天前移植了。您只需要稍微修改一下就可以得到您想要的结果。
1.通过将所有Action声明更改为Action<float>来使Action接受float参数,这意味着它将允许具有float参数的函数。
2.现在,通过更改TriggerEvent函数,使其接受一个float参数。
public static void TriggerEvent(string eventName)

为了

public static void TriggerEvent(string eventName, float h)

这是新的EventManager脚本。
using UnityEngine;
using System.Collections.Generic;
using System;

public class EventManager : MonoBehaviour
{

    private Dictionary<string, Action<float>> eventDictionary;

    private static EventManager eventManager;

    public static EventManager instance
    {
        get
        {
            if (!eventManager)
            {
                eventManager = FindObjectOfType(typeof(EventManager)) as EventManager;

                if (!eventManager)
                {
                    Debug.LogError("There needs to be one active EventManger script on a GameObject in your scene.");
                }
                else
                {
                    eventManager.Init();
                }
            }

            return eventManager;
        }
    }

    void Init()
    {
        if (eventDictionary == null)
        {
            eventDictionary = new Dictionary<string, Action<float>>();
        }
    }

    public static void StartListening(string eventName, Action<float> listener)
    {

        Action<float> thisEvent;
        if (instance.eventDictionary.TryGetValue(eventName, out thisEvent))
        {
            thisEvent += listener;
        }
        else
        {
            thisEvent += listener;
            instance.eventDictionary.Add(eventName, thisEvent);
        }
    }

    public static void StopListening(string eventName, Action<float> listener)
    {
        if (eventManager == null) return;
        Action<float> thisEvent;
        if (instance.eventDictionary.TryGetValue(eventName, out thisEvent))
        {
            thisEvent -= listener;
        }
    }

    public static void TriggerEvent(string eventName, float h)
    {
        Action<float> thisEvent = null;
        if (instance.eventDictionary.TryGetValue(eventName, out thisEvent))
        {
            thisEvent.Invoke(h);
        }
    }
}

测试:

public class Test : MonoBehaviour
{

    void OnEnable()
    {
        EventManager.StartListening("OnPlayerTeleport", TeleportPlayer);
    }

    void OnDisable()
    {
        EventManager.StopListening("OnPlayerTeleport", TeleportPlayer);
    }

    void Update()
    {
        if (Input.GetButtonDown("Teleport"))
        {
            EventManager.TriggerEvent("OnPlayerTeleport", 5);
        }
    }

    void TeleportPlayer(float h)
    {
        float yPos = transform.position.y;
        yPos += h;
        transform.position = new Vector3(transform.position.x, yPos, transform.position.z);
    }
}

1
好的,谢谢。但我可以问一个问题吗?如果我有很多函数,其中一些具有 float 参数,一些具有 string 参数,而另一些则没有参数怎么办? - Alexandr Köln
1
另一种方法是使用“params”关键字传递无限变量。不要将类型设置为“float”或“string”,而应将其设置为“object”类型。然后,您可以将对象转换为“float”或“string”。我给你的建议是只传递你需要的内容。不要创建一个可以在其参数中传递每种数据类型的EventSystem。这会减慢游戏速度。 - Programmer
好的。如果我将所有变量存储在我的GameManager类中(我使用单例),并且每个需要使用其实例变量的函数都将使用它实例中的变量,会怎样呢? 例如:在我的GameManager中float height = 15.0f;,然后在函数中我只需使用GameManager.instance.height? 我的意思是,这样做会更快,对代码来说更优化吗? - Alexandr Köln
您可以使用任何类,但单例模式并不会以任何方式提高代码速度。它仅用于拥有一个类的实例。我建议您在C#中阅读更多关于单例模式的内容。 - Programmer
1
这个问题特别涉及到UnityEvent,而不是寻找替代方案。 - John Stock
显示剩余3条评论

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接