Pass parameters with UnityAction

14,437

Here is the problem:

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

The action argument does not accept any parameter but you are passing it a function that requires a parameter:

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

with:

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

Notice the 2 passed to the ActivateQuest function.


Passing parameter to UnityEvent is not really that simple as one would expect. You must derive from UnityEvent and also provide the type of parameter. In this case you want to pass int. You must create a class that derives from UnityEvent with int as generic.

public class IntUnityEvent : UnityEvent<int>{}

The IntUnityEvent action variable can then be passed around as parameter in your functions instead of UnityAction action.

Below is a simplified and generic solution provided so that it will be helpful to others too. Just add your other parameters to the PopulateConversationList function and you should be good to go. It's well commented.

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

Note:

If possible, avoid using UnityEvent in Unity. Use use C# Action and delegate since they are more easier to use. Also, they are much more faster than Unity's UnityEvent.

Share:
14,437
Majs
Author by

Majs

Updated on June 13, 2022

Comments

  • Majs
    Majs almost 2 years

    Trying to send an UnityAction as a parameter for one of my methods, like so:

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

    this works fine, but now I want to pass the following Action as a parameter:

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

    However, it will not work when I use an action that has a parameter:

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

    The above gives error: Cannot convert from void to UnityAction. How can I pass a UnityAction with a parameter, as a parameter?

    I call the Action in the conversation like this:

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

    EDIT: The solution I ended up going with:

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

    This way I can call several methods as well.

  • Majs
    Majs almost 7 years
    Thanks, Accepted cus it answers my question :) I ended up finding my own way, which also allows me to call several methods, which I need.
  • Selim Yildiz
    Selim Yildiz about 4 years
    It could be better if you provide explanation how your solution works.
  • Display name
    Display name about 2 years
    This is a question about Unity c#, not general c#. There is a subtle but huge difference there. In Unity, you should not use Action, you should use UnityAction. Also, without the Register method, this answer is incomplete.