Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Universal type for any yield type

Trying to have a system able to store any kind of yield instructions

YieldInstruction m_yield;

void SetInstruction()
{
    switch(condition)
    {
        case UseWait:
            m_yield = new WaitForSeconds(1f);
            break;
        case UseWaitUntil:
            m_yield = new WaitUntil(() => flag == true); // Cannot cast here
    }
}

Changing the type to IEnumerator puts the problem on the first one. CustomeYieldInstruction is not doing either.

I can't put my finger on what is the relation between YieldInstruction and CustomYieldInstruction. Despite the names, one is its own base type and the latter is IEnumerator.

I'm also confused since the two methods can yield in a IEnumerator method but won't cast into it if done as I am trying.

public sealed class WaitForSeconds : YieldInstruction{ /* ** */ }
public class YieldInstruction { }

public sealed class WaitUntil : CustomYieldInstruction { /* ** */}
public abstract class CustomYieldInstruction : IEnumerator { /* ** */ }

and I can do :

public IEnumerator Sequence()
{
     yield return new WaitForSeconds(1f),
     yield return new WaitUntil(()=> condition == true);
}
like image 253
fafase Avatar asked Mar 25 '26 15:03

fafase


2 Answers

In addition to Menyus' answer

I'd say using object is a bit too dirty for my taste.

But you could simply build a wrapper IEnumerator for those types that do not implement it themselves (like anything based on the internal times):

private IEnumerator WaitForYieldInstruction(YieldInstruction instruction)
{
    yield return instruction;
}

and then use

IEnumerator m_yield;

void SetInstruction()
{
    switch(condition)
    {
        case UseWait:
            m_yield = WaitForYieldInstruction(new WaitForSeconds(1f));
            break;
        case UseWaitUntil:
            m_yield = new WaitUntil(() => flag); 
            break;
    }
}
like image 163
derHugo Avatar answered Mar 27 '26 06:03

derHugo


YieldInstruction gets special treatments from Unity's internal system. If you just look at WaitUntil it needs no special treatments from the internal Engine(C/C++) since it just expects a C# predicate. On the other hand WaitForSeconds, WaitForEndOfFrame ofc needs some special treatments. In the former one it needs the internal timer, in the latter one the coroutine scheduler have to make a special interrupt just at the end of frame which is kinda impossible with just the managed scripting side.

Also do not forget you can yield anything! null also does not implement IEnumerator nor string etc..

When you call StartCoroutine(MyCoroutine); you are basically registering the method into Unity's coroutine scheduler and it is implemented in C/C++.

Back to your original question. Luckily in C# every class inherits from System.Object so they can have a base class.

like image 24
Menyus Avatar answered Mar 27 '26 06:03

Menyus



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!