OK, pomyśl o rozwoju gry.
Załóżmy, że robisz cutscenkę lub samouczek. Tak czy inaczej, masz uporządkowaną sekwencję poleceń wysyłanych do pewnej liczby jednostek. Jednostka przesuwa się do miejsca, rozmawia z facetem, a potem idzie gdzie indziej. I tak dalej. Niektóre polecenia nie mogą zostać uruchomione, dopóki inne nie zostaną zakończone.
Zobacz, jak działa Twoja gra. Każda klatka musi przetwarzać sztuczną inteligencję, testy kolizji, animację, rendering i dźwięk, między innymi. Możesz myśleć tylko o każdej klatce. Więc w jaki sposób umieścić ten kod w, gdzie trzeba czekać na zakończenie jakiejś czynności przed wykonaniem następnego?
Jeśli zbudowałeś system w C++, to co masz, to coś, co działało przed AI. Będzie miał sekwencję poleceń do przetworzenia. Niektóre z tych poleceń byłyby natychmiastowe, jak "powiedz jednostce X, aby tu" lub "odradzać istotę Y tutaj". Inni będą musieli poczekać, np. "Powiedz jednostce Z, aby tu przybyła i nie przetwarzaj już poleceń, dopóki nie dotrze tutaj". Procesor poleceń musiałby być wywoływany w każdej klatce i musiałby rozumieć złożone warunki, takie jak "istota jest na miejscu" i tak dalej.
W Lua, to będzie wyglądać następująco:
local entityX = game:GetEntity("entityX");
entityX:GoToLocation(locX);
local entityY = game:SpawnEntity("entityY", locY);
local entityZ = game:GetEntity("entityZ");
entityZ:GoToLocation(locZ);
do
coroutine.yield();
until (entityZ:isAtLocation(locZ));
return;
W C++ rozmiarze, należy wznowić ten skrypt raz na ramkę, dopóki nie zostanie zrobione. Po powrocie wiesz, że cutscena się skończyła, więc możesz zwrócić kontrolę użytkownikowi.
Zobacz, jak prosta jest logika Lua. Robi dokładnie to, co mówi. Jest to oczywiste, oczywiste i dlatego bardzo trudno jest się pomylić.
Mocą coroutines jest możliwość częściowego wykonania jakiegoś zadania, oczekiwania na spełnienie warunku, a następnie przejścia do następnego zadania.
Pochodzą z poprzedniego wieku. Wielordzeniowe cpus i kary za opóźnienia związane z odkładaniem pamięci podręcznej cpu są i kończą się ich użytecznością. Nici to jest. –
@Hans Passant: To całkowicie pomija punkt coroutines. Coroutines nie zastępują wątków i nie używasz ich do tego samego, do którego używasz wątków. Chodzi o to, aby napisać czysty i wygodny (niezwiązany z prądem!) Kod, w którym wywołanie funkcji może zostać wstrzymane, aby można było powrócić, gdy masz więcej informacji, bez blokowania głównej pętli. Nie ma na to żadnego wpływu, podobnie jak robi to lua. Gwinty systemu operacyjnego byłyby słabym substytutem w tym przypadku użycia. –