C# 将参数传递给UnityEvent

C# 将参数传递给UnityEvent,c#,unity3d,C#,Unity3d,好吧,我有点困惑。我通过教程学习了UnityEvent和消息传递系统。但我有一个问题,我无法理解。如何将参数传递给调用函数 例如(我有EventManager就像教程中的那样): 我有一个触发器: void Update () { if (Input.GetButtonDown ("Teleport")) { EventManager.TriggerEvent ("OnPlayerTeleport"); } } 但是,如果我想将“高度”值传递给函数“远程传送播放

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

例如(我有
EventManager
就像教程中的那样):

我有一个触发器:

void Update () {
    if (Input.GetButtonDown ("Teleport")) {
        EventManager.TriggerEvent ("OnPlayerTeleport");
    }
}
但是,如果我想将“高度”值传递给函数“远程传送播放器”,该怎么办

void TeleportPlayer (float h) {
    float yPos = transform.position.y;
    yPos += h;
    transform.position = new Vector3 (transform.position.x, yPos, transform.position.z);
}
我该怎么做呢?

使用C#委托/操作,而不是Unity的
UnityEvent
。这比Unity的活动要快。我几天前搬家了。你只需要稍微修改一下就可以得到你想要的

1。通过将所有
Action
声明更改为
Action
,使
Action
执行
float
,这意味着它将允许带有
float
参数的函数

2。现在,使
TriggerEvent
函数采用
float
参数。通过改变

public static void TriggerEvent(string eventName)

下面是新的
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);
        }
    }
}

好的,谢谢。但我能再问一个问题吗?如果我有很多函数,其中一些函数有
float
参数,一些函数有
string
,而一些函数没有参数,那会怎么样?@AlexandrKöln从这里开始很复杂,但可以完成。您可以创建一个名为AllData的类,然后在其中包含所有变量。可能是数组字符串或浮点数。然后,将float参数更改为AllData类类型。现在您可以传递一个包含所有信息的类。另一种方法是使用
params
关键字传递无限变量。将类型设置为float或string
,而不是设置为
object`type。然后,您可以将对象投射到
float
string
或从中投射对象。我给您的建议是只传入您需要的内容。不要使EventSystem可以传递其参数中的所有数据类型。这会减慢你的比赛速度。好的。如果我将所有变量存储在GameManager类中(我使用singleton),并且我需要的每个函数都将使用它实例中的变量,那会怎么样?例如:
float height=15.0f
在我的GameManager中,在函数中,我将只使用
GameManager.instance.height
?我的意思是,对于代码来说,这将更快、更优化?您可以使用任何您想要的类,但singleton不会以任何方式使代码更快。它只是用来拥有一个类的实例。我建议你多读一些关于C#中的singleton。
public static void TriggerEvent(string eventName, float h)
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);
    }
}