LINUX.ORG.RU

История изменений

Исправление dissident, (текущая версия) :

Я не уверен, что они бесстековые (см. ниже примеры с int steps и CustomYieldInstruction).

Еще я хотел обратить внимание, что у них шедулер есть. Ну тот же, что каждый frame запускает update для MonoBehavior навешанных на GameObject.

Т.е. например в игре есть DoomGuy (GameObject), у него есть Shotgun (MonoBehavior) и Legs (MonoBehavior), Legs запускают две корутины WalkLeftLeg(), WalkRightLeg(), тогда каждый фрейм будет вызываться:

Shotgun.Update();
Legs.Update();
WalkLeftLeg().ResumeTillYield(); // psedocode
WalkRightLeg().ResumeTillYield(); // psedocode

«без всякого усилия само по себе».

Поэтому IMHO это fiber’ы. Пусть и бесстековые. Хотя почему бесстековые. Я же в начале корутины могу объявить int steps и оно будет в стэке корутины. И если я ему буду делать steps++ как-нибудь так:

class Legs: public MonoBehavior
{
    IEnumerator WalkLeftLeg()
    {
        int steps = 0;
        while (true)
        {
            yield return null;
            steps++;
        }
    }

    IEnumerator WalkRightLeg()
    {
        int steps = 0;
        while (true)
        {
            yield return null;
            steps++;
        }
    }

    IEnumerator Start()
    {
         StartCoroutine("WalkLeftLeg");
         StartCoroutine("WalkRightLeg");
    }

    void Update()
    {
        // do something
    }
}

steps будет инкрементироваться после каждого вызова Resume() для каждой «корутины ноги».

Или я неправильно понимаю понятие «бесстековая корутина»?

Что касается yield() на верхнем уровне - это не до конца так. Можно создать свою yield instruction, которую yield’ить из своей корутины: https://docs.unity3d.com/ScriptReference/CustomYieldInstruction.html. Так например реализованы всякие WaitForSeconds(int). В своей корутине можно делать yield new WaitForSeconds(5) и это как бы и будет корутина, которая вызывает другу корутину и yield’ит ее результат. Если под стэком имелось ввиду это, то он есть.

В общем IMHO - это fiber’ы. Пусть и трэд один (тот, что их дергает каждый фрейм).

Исправление dissident, :

Я не уверен, что они бесстековые (см. ниже пример с int a). Еще я хотел обратить внимание, что у них шедулер есть. Ну тот же, что каждый frame запускает update для MonoBehavior навешанных на GameObject.

Т.е. например в игре есть DoomGuy (GameObject), у него есть Shotgun (MonoBehavior) и Legs (MonoBehavior), Legs запускают две корутины WalkLeftLeg(), WalkRightLeg(), тогда каждый фрейм будет вызываться:

Shotgun.Update();
Legs.Update();
WalkLeftLeg().ResumeTillYield(); // psedocode
WalkRightLeg().ResumeTillYield(); // psedocode

«без всякого усилия само по себе».

Поэтому IMHO это fiber’ы. Пусть и бесстековые. Хотя почему бесстековые. Я же в начале корутины могу объявить int a и оно будет в стэке корутины. И если я ему буду делать a++ как-нибудь так:

class Legs: public MonoBehavior
{
    IEnumerator WalkLeftLeg()
    {
        int a = 0;
        while (true)
            yield return null;
        a++
    }

    IEnumerator WalkRightLeg()
    {
        int a = 0;
        while (true)
            yield return null;
        a++
    }

    IEnumerator Start()
    {
         StartCoroutine("WalkLeftLeg");
         StartCoroutine("WalkRightLeg");
    }

    void Update()
    {
        // do something
    }
}

a будет инкрементироваться после каждого вызова Resume() для каждой «корутины ноги».

Что касается yield() на верхнем уровне - это не до конца так. Можно создать свою yield instruction, которую yield’ить из своей корутины: https://docs.unity3d.com/ScriptReference/CustomYieldInstruction.html

В общем IMHO - это fiber’ы. Пусть и трэд один (тот, что их дергает каждый фрейм).

Исправление dissident, :

Я не уверен, что они бесстековые (см. ниже пример с int a). Еще я хотел обратить внимание, что у них шедулер есть. Ну тот же, что каждый frame запускает update для MonoBehavior навешанных на GameObject.

Т.е. например в игре есть DoomGuy (GameObject), у него есть Shotgun (MonoBehavior) и Legs (MonoBehavior), Legs запускают две корутины WalkLeftLeg(), WalkRightLeg(), тогда каждый фрейм будет вызываться:

Shotgun.Update();
Legs.Update();
WalkLeftLeg().ResumeTillYield();
WalkRightLeg().ResumeTillYield();

«без всякого усилия само по себе».

Поэтому IMHO это fiber’ы. Пусть и бесстековые. Хотя почему бесстековые. Я же в начале корутины могу объявить int a и оно будет в стэке корутины. И если я ему буду делать a++ как-нибудь так:

class Legs: public MonoBehavior
{
    IEnumerator WalkLeftLeg()
    {
        int a = 0;
        while (true)
            yield return null;
        a++
    }

    IEnumerator WalkRightLeg()
    {
        int a = 0;
        while (true)
            yield return null;
        a++
    }

    IEnumerator Start()
    {
         StartCoroutine("WalkLeftLeg");
         StartCoroutine("WalkRightLeg");
    }

    void Update()
    {
        // do something
    }
}

a будет инкрементироваться после каждого вызова Resume() для каждой «корутины ноги».

Что касается yield() на верхнем уровне - это не до конца так. Можно создать свою yield instruction, которую yield’ить из своей корутины: https://docs.unity3d.com/ScriptReference/CustomYieldInstruction.html

В общем IMHO - это fiber’ы. Пусть и трэд один (тот, что их дергает каждый фрейм).

Исходная версия dissident, :

Я не уверен, что они бесстековые (см. ниже пример с int a). Еще я хотел обратить внимание, что у них шедулер есть. Ну тот же, что каждый frame запускает update для MonoBehavior навешанных на GameObject.

Т.е. например в игре есть DoomGuy (GameObject), у него есть Shotgun (MonoBehavior) и Legs (MonoBehavior), Legs запускают две корутины WalkLeftLeg(), WalkRightLeg(), тогда каждый фрейм будет вызываться:

Shotgun.Update();
Legs.Update();
WalkLeftLeg().ResumeTillYield();
WalkRightLeg().ResumeTillYield();

«без всякого усилия само по себе».

Поэтому IMHO это fiber’ы. Пусть и бесстековые. Хотя почему бесстековые. Я же в начале корутины могу объявить int a и оно будет в стэке корутины. И если я ему буду делать a++ как-нибудь так:

class Legs: public MonoBehavior
{
    IEnumerator WalkLeftLeg()
    {
        int a = 0;
        while (true)
            yield return null;
        a++
    }

    IEnumerator WalkRightLeg()
    {
        int a = 0;
        while (true)
            yield return null;
        a++
    }

    IEnumerator Start()
    {
         StartCoroutine("WalkLeftLeg");
         StartCoroutine("WalkRightLeg");
    }

    void Update()
    {
        // do something
    }
}

a будет инкрементироваться после каждого вызова Resume() для каждой «корутины ноги».

Что касается yield() на верхнем уровне - это не до конца так. Можно создать свою yield instruction, которую yield’ить из своей корутины: https://docs.unity3d.com/ScriptReference/CustomYieldInstruction.html