Is it possible to add a coroutine to an event? I’m experimenting with events, and it seems like it would be extremely useful. However, I’ve got to run a coroutine for one of the functions that will be assigned to the event. Don’t know if I’m explaining this correctly so here’s some code:
Event declaration:
public delegate void BookSelectEventHandler();
public static event BookSelectEventHandler BookSelect;
public static void OnBookSelect()
{
BookSelectEventHandler bookSelect = BookSelect;
if (bookSelect != null)
bookSelect();
}
Basically what I want to do (but not a solution):
BookSelect += StartCoroutine(RenderWholeBook);
My function:
IEnumerator RenderWholeBook()
{
//snap
yield return null; //return next frame
//change text
yield return null; //return next frame
//snap next page
yield return null; //return next frame
//turn off
yield break;
}
Is this even a viable approach? Or should I just do the long work around of reference and call the function?
Also thought about this:
public delegate void BookSelectEventHandler();
public static event BookSelectEventHandler BookSelect;
public static void OnBookSelect()
{
BookSelectEventHandler bookSelect = BookSelect;
if (bookSelect != null)
StartCoroutine(bookSelect());
}
I’m not sure what your intentions are, but you can’t start a directly coroutine from a static method since StartCoroutine is a member method from MonoBehaviour. Another problem is that the event handlers must be a coroutine, so they must return IEnumerator.
public delegate IEnumerator BookSelectEventHandler();
public static event BookSelectEventHandler BookSelect;
public void OnBookSelect()
{
if (BookSelect != null)
StartCoroutine(BookSelect());
}
static IEnumerator RenderWholeBook()
{
//snap
yield return null; //return next frame
//change text
yield return null; //return next frame
//snap next page
yield return null; //return next frame
//turn off
yield break;
}
(...)
BookSelect += RenderWholeBook;
However there’s a problem: only the last handler is called.
Your delegate needs to return an IEnumerator, as well as BookSelect's function, which is probably assigned from elsewhere. Then, you call StartCoroutine(bookSelect());
You can get past this with one more level of functionality.I actually hit the same problem
//delegate
public delegate void BookSelectEventHandler();
//event
public event BookSelectEventHandler BookSelect;
//Trigger Event Function
public void OnBookSelect()
{
if (BookSelect != null)
BookSelect();
}
//The function we want to run as a coroutine
IEnumerator RenderWholeBook()
{
//snap
yield return null; //return next frame
//change text
yield return null; //return next frame
//snap next page
yield return null; //return next frame
//turn off
yield break;
}
//Helper function that gets registered on the event and //calls the actual function we want to run as a coroutine //without waiting for it.
public void HelperFunction(){
StartCoroutine(RenderWholeBook);
}
(...)
//In a Start/Awake/OnEnable/WhateverEventRegistering code //you use
BookSelect += HelperFunction;
This way when you register listeners to the BookSelect event they won’t be IEnumerators and won’t stumble on the restriction of just using the last listener/handler whatever you want to call it.
The problem is when you want to wait for the coroutine to finish…if you do then you can’t use a helper function because you’d need to yield return the RenderWholeBook which means you have to declare whatever function is going to call the “yield return …” piece of code.Which is kind of a chain reaction towards the parent function.
Calling StartCoroutine creates the coroutine and exits.Which means that if you need info about this you have to pass them through arguments.
Can’t you just make the event a void instead? You then use that void event to call your IEnumerator.
Also, note that on events you should likely be stopping your last IEnumerator!
public delegate void BookSelectEventHandler();
public static event BookSelectEventHandler BookSelect;
public static void OnBookSelect()
{
if (BookSelect != null)
BookSelect();
}
Start()
{
BookSelect += MyBookSelectHandler;
}
IEnumerator lastEnumerator = null;
public void MyBookSelectHandler()
{
if (lastEnumerator != null)
StopCoroutine(lastEnumerator);
lastEnumerator =RenderWholeBook();
StartCoroutine(lastEnumerator);
}
IEnumerator RenderWholeBook()
{
//snap
yield return null; //return next frame
//change text
yield return null; //return next frame
//snap next page
yield return null; //return next frame
//turn off
yield break;
}