История изменений
Исправление 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