使用UnityAction传递参数

时间:2017-06-18 13:23:07

标签: c# unity3d unity5

尝试将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);

这很好用,但现在我想将以下Action作为参数传递:

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

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

4 个答案:

答案 0 :(得分:2)

问题在于:

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

with:

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

注意2传递给ActivateQuest函数。

将参数传递给UnityEvent并不像人们期望的那么简单。您必须从UnityEvent派生,并提供参数类型。在这种情况下,您想传递int。您必须创建一个派生自UnityEvent且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快得多。

答案 1 :(得分:0)

您可以使用类似的东西

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

答案 2 :(得分:0)

这应该有效

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

答案 3 :(得分:0)

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

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