【问题标题】:Pass argument to UnityEvent将参数传递给 UnityEvent
【发布时间】:2017-02-12 04:02:57
【问题描述】:

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

例如(我在教程中有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);
}

我该怎么做?

【问题讨论】:

    标签: c# unity3d


    【解决方案1】:

    使用 C# 委托/动作代替 Unity 的 UnityEvent。它比 Unity 的事件要快。我几天前移植了it。您只需稍作修改即可获得所需的内容。

    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);
        }
    }
    

    【讨论】:

    • 好的,谢谢。但我可以再问一个问题吗?如果我有很多函数,其中一些有 float 参数,一些有 string,还有一些没有参数怎么办?
    • @AlexandrKöln 从那里开始很复杂,但可以做到。您可以创建一个名为 AllData 的类,然后在其中包含所有变量。也许是数组字符串或浮点数。然后,将 float 参数更改为该 AllData 类类型。现在你可以传递一个包含你所有信息的类。
    • 另一种方法是使用params 关键字来传递无限的变量。而不是创建类型 float or string, make it object` 类型。然后,您可以将对象投射到floatstring 或从string 我的建议是只传递你需要的东西。不要创建可以在其参数中传递每种数据类型的 EventSystem。这会减慢您的游戏速度。
    • 好的。如果我将所有变量存储在我的 GameManager 类中(我使用单例),并且我需要的每个函数都将使用它实例中的变量怎么办?例如:float height = 15.0f; 在我的 GameManager 中,而在函数中我将只使用 GameManager.instance.height?我的意思是,这对于代码来说会更快、更优化吗?
    • 你可以使用任何你想要的类,但是单例不会以任何方式使代码快速。它只是用来拥有一个类的一个实例。我建议您阅读有关 C# 中单例的更多信息。
    猜你喜欢
    • 2016-09-03
    • 2019-09-27
    • 1970-01-01
    • 1970-01-01
    • 2013-01-27
    • 2013-11-19
    • 2011-01-06
    • 2013-07-19
    相关资源
    最近更新 更多