Hallo Garzec,
dein Weg ist tatsächlich sehr unsauber und produziert Unmengen von Overhead für eine simple Routine. Das liegt nicht nur am allgemeinen Overhead von Coroutinen (2x System-Calls nötig: moveNext und current, sowie eine weitere GC alloc in jedem Frame), sondern auch an der Tatsache das du z.B. dein WaitForSeconds nicht cachest. Um Missverständnisse außerdem aus dem Weg zu räumen: Coroutinen sind NICHT parallel und damit KEINE Threads (in Bezug auf Sneyke's Kommentar). Sie sind lediglich eine Art von State-Machine mit einem eigenständigen Update-Call im selbem Unity-Thread, wobei dieser nach den Kriterien des yield-Objekts in den Code zurück kehrt.
Hier ein Beispiel zum cachen:
|
C#-Quelltext
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
WaitForSeconds wait = new WaitForSeconds(1.0f);
void Start()
{
StartCoroutine(Coroutine());
}
IEnumerator Coroutine()
{
//do something...
yield return wait;
//do something else after that...
}
|
Der Weg mit der Update (Sneyke's Vorschlag) finde ich am saubersten. Die InvokeRepeating wäre eine simple Alternativlösung, jedoch finde ich Unity's Weg mit der Suche einer Methode über einen String im selben MonoBehaviour ziemlich schlecht (Wozu die Suche, ich weiß doch wo die Methode liegt?!). InvokeRepeating ist demzufolge auch in keiner Klasse verfügbar die nicht von MonoBehaviour ableitet.
Hier Sneyke's Besipiel erweitert, damit etwas nach einem definierbaren Step aufgerufen wird:
|
C#-Quelltext
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
class DayTime {
private float actualTime;
private float stepTimeForInvoke;
private float lastInvokedStep;
private float dayCycleTimeInSec;
private stepCallback;
private fullDayCallback;
public DayTime(float dayCycleTimeInSec, float stepTimeForInvoke, Action stepCallback, Action fullDayCallback) {
this.dayCycleTimeInSec = dayCycleTimeInSec;
this.stepTimeForInvoke = stepTimeForInvoke;
this.stepCallback = stepCallback;
this.fullDayCallback = fullDayCallback;
}
public void AddTime(float time) {
actualTime += time;
if(actualTime >= lastInvokedStep + stepTimeForInvoke) {
stepCallback?.Invoke();
lastInvokedStep = actualTime;
}
if(time >= dayCycleTimeInSec) {
fullDayCallback?.Invoke();
actualTime -= dayCycleTimeInSec;
float restStepFromLastDay = lastInvokedStep - actualTime;
lastInvokedStep = restStepFromLastDay;
}
}
}
|
PS: Coroutinen sind laut Entwickler-Blog 5x langsamer als Updates. Wobei eine Vielzahl von Updates in verschieden MonoBehaviours gegenüber einem Array in einem Manager ebenfalls 4x langsamer ist. Verteilte Coroutinen sind also gegenüber einer zentralen Update-Stelle bis zu 20x langsamer.
https://blogs.unity3d.com/2015/12/23/1k-update-calls/