使用 UnityAction 传递参数

Pass parameters with UnityAction

尝试发送一个 UnityAction 作为我的方法之一的参数,如下所示:

public void PopulateConversationList(string [] fullConversation, string onLastPagePrompt, string npcName, int stage, UnityAction action)
{
    conversations.Add(new Conversation(fullConversation, onLastPagePrompt, npcName, stage, action));
}

dialogHolder.PopulateConversationList(stage1, "Okay", _name, 1, QuestManager.Instance().ActivateQuest);

这工作正常,但现在我想将以下操作作为参数传递:

public void ActivateQuest(int questId)
{
    Debug.Log("This is the id: " + questId);
}

但是,当我使用具有参数的操作时,它将不起作用:

dialogHolder.PopulateConversationList(stage1, "Okay", _name, 1, QuestManager.Instance().ActivateQuest(2));

以上给出错误:Cannot convert from void to UnityAction。 如何传递带有参数的 UnityAction 作为参数?

我在对话中这样称呼Action

dialog.OnAccept(ConvList[i].onLastPagePrompt, () =>
{
    ConvList[i].action();
    dialog.Hide();
});

编辑:我最终采用的解决方案:

enter dialogHolder.PopulateConversationList(stage1, "Okay", _name, 1, () =>
    {
        QuestManager.Instance().ActivateQuest(0);
    });

这样我也可以调用几个方法。

问题是:

public void PopulateConversationList(string[] fullConversation, string onLastPagePrompt, string npcName, int stage, UnityAction action)

action 参数不接受任何参数,但您正在向它传递一个需要参数的函数:

public void ActivateQuest(int questId)
{
    Debug.Log("This is the id: " + questId);
}

与:

dialogHolder.PopulateConversationList(stage1, "Okay", _name, 1, QuestManager.Instance().ActivateQuest(2));

注意传递给 ActivateQuest 函数的 2


UnityEvent传递参数并不像人们想象的那么简单。您必须派生自 UnityEvent 并提供参数类型。在这种情况下,你想传递 int。您必须创建一个从 UnityEvent 派生的 class,并使用 int 作为通用事件。

public class IntUnityEvent : UnityEvent<int>{}

然后 IntUnityEvent action 变量可以在您的函数中作为参数传递,而不是 UnityAction action

下面提供了一个简化的通用解决方案,对其他人也有帮助。只需将您的其他参数添加到 PopulateConversationList 函数中,您就可以开始了。评论很好。

[System.Serializable]
public class IntUnityEvent : UnityEvent<int>
{
    public int intParam;
}

public IntUnityEvent uIntEvent;

void Start()
{
    //Create the parameter to pass to the function
    if (uIntEvent == null)
        uIntEvent = new IntUnityEvent();

    //Add the function to call
    uIntEvent.AddListener(ActivateQuest);

    //Set the parameter value to use
    uIntEvent.intParam = 2;

    //Pass the IntUnityEvent/UnityAction to a function
    PopulateConversationList(uIntEvent);
}

public void PopulateConversationList(IntUnityEvent action)
{
    //Test/Call the function 
    action.Invoke(action.intParam);
}

//The function to call
public void ActivateQuest(int questId)
{
    Debug.Log("This is the id: " + questId);
}

:

如果可能,请避免在 Unity 中使用 UnityEvent。使用 C# Actiondelegate 因为它们更易于使用。此外,它们比 Unity 的 UnityEvent.

快得多

你可以使用这样的东西

    public void RegisterEvent<T, U, V>(object eventName, Action<T, U, V> handler)
{
    Register(eventName, handler);
}

这应该有效

    private void Awake()
    {
        UnityAction unityAction = null;
        unityAction += () => Jamen1("UnityAction Jamen1");
        unityAction += Jamen2;
        unityAction += () =>
        {
            print("UnityAction Jamen3");
        };
        Jamen3(unityAction)
    }

    void Jamen1(string text)
    {
        print(text);
    }

    void Jamen2()
    {
        print("UnityAction Jamen2");
    }

    void Jamen3(UnityAction unityAction)
    {
        unityAction?.Invoke();
    }

注:?是空检查。

// Null Check    
unityAction?.Invoke();

// Don't Null Check
unityAction.Invoke();

我用lambda表达式来解决这个问题

dialogHolder.PopulateConversationList(stage1, "Okay", _name, 1, () => {
    QuestManager.Instance().ActivateQuest(2);
});

所以,这里的每个人都没有解决 UnityAction 上的小于、大于运算符。

看来你对 void UnityAction 很熟悉

public void CallAction(UnityAction action){
    action?.invoke();
}

但是,假设您想传递一个浮点数。

public void SendFloat(UnityAction<float> action){
    action?.invoke(5.0f);
}

或者,如果你想传递一个浮点数和另一个动作

public void SendFloatAndAction(UnityAction<float, UnityAction> action){
    action?.invoke(5.0f, ()=>
    {
        Debug.Log("Called");
    });
}

基本上,您可以将所需的任何信息放入 UnityAction 的小于、大于运算符中,以允许将其作为参数传递。

如 Unity 文档中所述,未分配动作的 UnityAction 或 Delegate 为 null,尝试调用它会引发错误。您可以添加一个问号 (?),而不是为 null 检查添加额外的 2-3 行,如果它不为空,它只会调用 UnityAction 或 Delegate。

不幸的是,在查看了更好的 React 文档后,这些文档不足以满足我的口味,但这里是关于委托的 Unity Learn 教程:https://learn.unity.com/tutorial/delegates 这里是 UnityAction 的文档,尽管它们没有正确对待类型。 https://docs.unity3d.com/ScriptReference/Events.UnityAction.html https://docs.unity3d.com/ScriptReference/Events.UnityAction_4.html

如果您想使用 UnityAction,您必须通过在脚本顶部添加行 using UnityEngine.Events; 来使用 UnityEngine.Events。

最后一点,我没有对 UnityAction 调用进行太多试验,但我相信您只能设置 0 到 4 个参数。