使用 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# Action
和 delegate
因为它们更易于使用。此外,它们比 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 个参数。
尝试发送一个 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# Action
和 delegate
因为它们更易于使用。此外,它们比 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 个参数。