I am currently trying to make a coroutine dictionary under unity. The idea is, there are several characters, and when the player press a button it would call a function looking into a dictionary and running a coroutine corresponding to the character ability (as each character has different abilities).
Here is what my code looks like :
private string characterName // The name of the player's character
private Dictionary<string, IEnumerator> abilitiesDictionary = new Dictionary<string, IEnumerator>();
void Start() // I'm assigning values to the dictionary in the start function
{
abilitiesDictionary["character01"] = Routine01();
abilitiesDictionary["character02"] = Routine02();
}
void Update()
{
if (Input.GetKeyDown(KeyCode.A))
{
StartCoroutine(abilitiesDictionary[characterName]
}
}
private IEnumerator Routine01()
{
yield return new WaitForSeconds(1);
print("Routine 01 has run !")
}
private IEnumerator Routine02()
{
yield return new WaitForSeconds(1);
print("Routine 02 has run !")
}
However, I have a problem: the coroutine will only run once every scene reload. I can only run it once, after what it's just going not to work anymore. Is there anything I mistook about ? I didn't completely understood the way IEnumerator
got iterated when used for coroutines purposes in unity.
Thanks for your time and your answers
CodePudding user response:
Instead of storing the enumerator, store the function.
private Dictionary<string, Func<IEnumerator>> coroutines = new Dictionary<string, Func<IEnumerator>>();
Add routines to the dictionary
coroutines.Add("1", Routine1);
coroutines.Add("2", Routine2);
Execution
StartCoroutine(coroutines["1"].Invoke());
CodePudding user response:
An IEnumerator in C# is a thing that is used to traverse enumerables (IEnumerable). Mostly, this is used for iterating through collections (arrays, lists etc.). Once the enumerator is used for traversal, it should be reset to allow traversal again.
Your function Routine01
returns an IEnumerator. When you initialize the dictionary using this function, you call it (denoted by double parentheses after the function name - Routine01()
). This means you create an IEnumerator once. After that, no matter how many times you access the dictionary by key, you will be getting the same IEnumerator each time.
In Unity, IEnumerators are used for running multiple tasks in a pseudo-parallel. Simply put, when iterating this enumerator, Unity Engine magically iterates through this parallel task - it returns to your IEnumerator again and again until the task, described by it is over (in your case - until one second passes).
Your mistake is using the same IEnumerator every time (you create it once with Routine01()
, and access it with each key press). Unity can't iterate through your IEnumerator, if the iterating is already over. It would simply do nothing. You should either generate a new IEnumerator each time you press the key, or call Reset() on the existing enumerator, so Unity could re-iterate through it.
@hijinxbassist showed in his answer how to achieve the former (generating new IEnumerator every time)