У меня есть следующая сопрограмма в единстве:
IEnumerator DoActionUponReachingRangeCoroutine(Range range, Delegate action, params object[] args)
{
yield return new WaitUntil(() => range.isPlayerInRange);
action.DynamicInvoke(args);
yield return null;
}
Как вы можете видеть, он может выполнять некоторые действия при выполнении условия range.IsPlayerInRange. Я хотел бы сделать то же самое, но с предоставлением собственного условия каждый раз, когда я вызываю этот метод, а не с жестко запрограммированным isPlayerInRange. Я просто предоставляю делегата вместо диапазона?
WaitUntil
принимает Func<bool>, поэтому вы можете просто передать это:
IEnumerator DoActionUponCoroutine(Func<bool> predicate, Delegate action, params object[] args)
{
yield return new WaitUntil(predicate);
action.DynamicInvoke(args);
yield return null;
}
Вы также можете предпочесть Action
для обратного вызова, что намного эффективнее, чем DynamicInvoke
:
IEnumerator DoActionUponCoroutine(Func<bool> predicate, Action action)
{
yield return new WaitUntil(predicate);
action();
yield return null;
}
Существует также способ использования общего TState state
и обратного вызова Action<TState>
, чтобы избежать захвата контекстов, но... это более сложный сценарий.
Я также думаю, что финал yield return null;
на самом деле излишен - за исключением того, что ОП действительно требует ожидания дополнительного кадра в конце
Найдите отражение C#, чтобы создать клон вашей функции, если вы хотите написать свою функцию один раз, но реплицировать ее отдельно.
Получить информацию о методе
MethodInfo mInfo = typeof(Program).GetMethod("SlotClick"); // inside the loop!!
https://learn.microsoft.com/en-us/dotnet/api/system.reflection.methodinfo?view=net-8.0
Затем создайте общий метод, изменяя параметры на тип или типы по мере необходимости. Документы объясняют,
Заменяет элементы массива типов на параметры типа текущего определения универсального метода и возвращает MethodInfo.
Ниже вы увидите мой пример создания кнопок пользовательского интерфейса и включения типа.
public class ShieldButton {
public string ButtonImg;
public void activateSheild() {
// ...
};
}
public class Button {
// this is the method we will get the method info of!
// we are going to change the method parameters in the for loop when cloning.
// then we will invoke the cloned method..
public void click<T>(T Type) {
switch (typeOf(Type)) {
case ShieldButton: { Type.activateShield() };
}
}
}
public class CreateMenu {
public void InitiateMenu()
{
for (int i = 0; i < inventorySize; i++)
{
MethodInfo mInfo = typeof(Button).GetMethod("click"); // Grab the class and method!
MethodInfo newInfo = mInfo.MakeGenericMethod(typeof(ShieldButton)); // make a clone of the method changing the parameter type to our ShieldButton Class!
ShieldButton shieldButton = new ShieldButton(); // Create a new version of the shield button class
newSlot.GetComponent<Button>().onClick.AddListener(newInfo.Invoke(null, shieldButton)); // Invoke the new methodInfo passing in the class to switch on!!!!
}
}
}
Вы можете передать что-то вроде
Func<bool>
, что означает «что-то, возвращающее bool».