So I performed tests on calling coroutines from another script. I want to understand why the results aren't the expected behavior in one of the test case, and unfortunately the one that I needed to use (as it is more dynamic).
Tests:
// TEST 1: Running coroutines from passed IEnumerator
m_Tester.StartCoroutine(1);
// TEST 2: Running coroutines in this script through a delegate
m_TesterByFunc.StartCoroutineByFunc(1);
// TEST 3: Running coroutines by starting them publicly via this script
m_TesterByCasting.StartCoroutineByCasting(1);
The idea is I'd like to call coroutines from another script - in this case, from a plain class. And I'm expecting that my coroutines would run normally. However, the problem is when passing IEnumerator to the Tester class, along with the owning Monobehavior object, then starting the coroutines from it (Tester class) only worked once. Calling StartCoroutine from CoroutineTest via a delegate function or publicly worked as intended.
I'm not sure if anyone has encountered this but I'd love to know why I'm getting the unexpected result particularly for Test #1.
- Is there a problem with passing IEnumerator and caching them in the class and the reason why it only works once? Is it not passed by reference?
Please see the test scripts below.
Script 1:
public class Tester
{
public delegate void Function();
private MonoBehaviour m_Owner;
private Function m_F1;
private Function m_F2;
private IEnumerator m_One;
private IEnumerator m_Two;
public Tester (MonoBehaviour owner)
{
m_Owner = owner;
}
public Tester(MonoBehaviour owner, IEnumerator one, IEnumerator two)
{
m_Owner = owner;
m_One = one;
m_Two = two;
}
public Tester(MonoBehaviour owner, Function f1, Function f2)
{
m_Owner = owner;
m_F1 = f1;
m_F2 = f2;
}
public void StartCoroutine(int index)
{
if (index == 0)
{
m_Owner.StopCoroutine(m_Two);
m_Owner.StartCoroutine(m_One);
}
if (index == 1)
{
m_Owner.StopCoroutine(m_One);
m_Owner.StartCoroutine(m_Two);
}
}
public void StartCoroutineByFunc(int index)
{
if (index == 0)
{
m_F1();
}
if (index == 1)
{
m_F2();
}
}
public void StartCoroutineByCasting(int index)
{
var test = (m_Owner as CoroutineTest);
if (index == 0)
{
test.StopCoroutine(test._TestTwoByCasting());
test.StartCoroutine(test._TestOneByCasting());
}
if (index == 1)
{
test.StopCoroutine(test._TestOneByCasting());
test.StartCoroutine(test._TestTwoByCasting());
}
}
}
Script 2: Attach to a game object in the scene
public class CoroutineTest : MonoBehaviour
{
private Tester m_Tester;
private Tester m_TesterByFunc;
private Tester m_TesterByCasting;
private void Awake()
{
m_Tester = new Tester(this, _TestOne(), _TestTwo());
m_TesterByFunc = new Tester(this, TestOneByFunc, TestTwoByFunc);
m_TesterByCasting = new Tester(this);
}
private void OnEnable()
{
// TEST 1: Running coroutines from passed IEnumerator
m_Tester.StartCoroutine(1);
// TEST 2: Running coroutines in this script through a delegate
m_TesterByFunc.StartCoroutineByFunc(1);
// TEST 3: Running coroutines by starting them publicly via this script
m_TesterByCasting.StartCoroutineByCasting(1);
}
public IEnumerator _TestOne()
{
Debug.Log("Test one");
yield return new WaitForSeconds(3f);
m_Tester.StartCoroutine(1);
}
public IEnumerator _TestTwo()
{
Debug.Log("Test two");
yield return new WaitForSeconds(3f);
m_Tester.StartCoroutine(0);
}
private void TestOneByFunc()
{
StopCoroutine(_TestTwoByFunc());
StartCoroutine(_TestOneByFunc());
}
private void TestTwoByFunc()
{
StopCoroutine(_TestOneByFunc());
StartCoroutine(_TestTwoByFunc());
}
private IEnumerator _TestOneByFunc()
{
Debug.Log("Test one by func");
yield return new WaitForSeconds(3f);
m_TesterByFunc.StartCoroutineByFunc(1);
}
private IEnumerator _TestTwoByFunc()
{
Debug.Log("Test two by func");
yield return new WaitForSeconds(3f);
m_TesterByFunc.StartCoroutineByFunc(0);
}
public IEnumerator _TestOneByCasting()
{
Debug.Log("Test one by casting");
yield return new WaitForSeconds(3f);
m_TesterByCasting.StartCoroutineByCasting(1);
}
public IEnumerator _TestTwoByCasting()
{
Debug.Log("Test two by casting");
yield return new WaitForSeconds(3f);
m_TesterByCasting.StartCoroutineByCasting(0);
}
}
Thanks!