Ene mene mu, wo bist du?
13. November 2013 von Yhoko
Wenn jemand an uns vorbeiläuft, merken wir das in der Regel recht schnell. Ganz anders sieht das bei NPCs bzw. Gegnern in Videospielen aus. Woher soll der NPC wissen, dass ein Spieler auf ihn zusteuert? Prinzipbedingt gibt es zwei Methoden, dieses Problem zu lösen. Die erste heisst "Polling" und bedeutet, dass der NPC regelmässig die Distanz zum Spieler misst. Ist diese Distanz ausreichend gering, darf er den Spieler bemerken und entsprechend agieren. Diese Methode kann man gut bei Singleplayer-Spielen einsetzen, wo mit jedem Bild (ca. 60 Mal pro Sekunde) auch die ganze Logik berechnet wird. Ein NPC kann hier also etwa alle 20 ms schauen was um ihn herum passiert.
Wie früher bereits erwähnt ist dieses Vorgehen jedoch unzuverlässig. Angenommen, die Framerate bricht extrem ein, weil Windows gerade Updates installiert. Der Spieler könnte dabei in einem Frame noch meilenweit vom NPC entfernt sein und bereits im nächsten Frame ein gutes Stück hinter ihm stehen. Da zwischen den Frames kein Polling stattfinden kann, würde der NPC davon nichts bemerken. Dies gilt natürlich nur, wenn die Bewegung des Spielers an die Zeit statt an die Framerate gekoppelt ist – bei besonders billigen Spielen wird die Figur einmal pro Frame ein Stück weit bewegt, meist auch direkt abhängig davon, ob eine Pfeiltaste bzw. WASD in diesem Frame gedrückt ist. Kleiner Exkurs: Diese Konstellation ist umso unzuverlässiger, je schneller der Spieler sich bewegt. Angenommen er bewegt sich normalerweise mit 4 Pixeln pro Frame über eine Tile-Map à jeweils 16x16 Pixel, funktioniert das noch ganz gut. Beschleunigt er aber irgendwie auf 32 Pixel pro Frame, würde er einzelne Tiles glatt überspringen, was die Kollisionsabfrage sabotiert.
Zurück zu Endyr, wo oben genannte Lösung nicht nur unzuverlässig sondern unmöglich zu implementieren wäre, denn der Server berechnet keine Frames. Im besten Fall kennt er die Position, wo der Spieler zu Laufen beginnt, und erst wieder die, wo er nach seinem Weg zum Stehen kommt. Ich sage "bester Fall" weil dabei absolut nichts berechnet werden muss, was die Serverauslastung gering hält. Der Server muss dabei nur wissen, wie lange der Spieler für seinen Weg braucht. Ist dieser Zeit abgelaufen, stellt er ihn auf den Zielpunkt und interessiert sich nicht weiter dafür, wo er tatsächlich langgelaufen ist. Aber halt, ermöglicht das kein Cheating? Kurze Antwort: Nein. Der Trick ist, den Weg im Voraus zu prüfen und zu schauen, ob alles seine Richtigkeit hat. Statt also 60x pro Sekunde den Weg häppchenweise abzulaufen und Kollisionen zu testen geschieht das alles in dem Moment, wo der Spieler losläuft. Und hier liegt nun auch der Hund begraben, wenn es darum geht, dass ein NPC den Spieler bemerken soll. Statt dass der NPC Polling betreibt und quasi jeden Schritt des Spielers beobachtet, prüft der Server zu Beginn, ob der Spieler bei einem oder mehreren NPCs vorbeikommt. Falls ja, werden Timer gesetzt und im entsprechenden Moment die NPCs über die Annäherung informiert. Ausser natürlich, der Spieler würde unterwegs eine neue Route einschlagen oder stehen bleiben – in diesem Fall werden alle Timer aktualisiert bzw. entfernt.
Das alles dient freilich nur der Performance – Alternativ kann auch jeder NPC regelmässig (sagen wir gnädigerweise 1x die Sekunde) die Spieler beobachten. Was das "kostet" kann man dabei selbst ausrechnen; angenommen es wuseln 20 Gegner und 3 Spieler im Level herum bedeutet dies 20 Skripts pro Sekunde, von denen jedes eine Schleife mit 3 Spielern abarbeitet bzw. zu jedem die Distanz misst. Polling ist eben teuer. Und damit endet unser kleiner Einblick ins effiziente NPC-Skripting.
Wie früher bereits erwähnt ist dieses Vorgehen jedoch unzuverlässig. Angenommen, die Framerate bricht extrem ein, weil Windows gerade Updates installiert. Der Spieler könnte dabei in einem Frame noch meilenweit vom NPC entfernt sein und bereits im nächsten Frame ein gutes Stück hinter ihm stehen. Da zwischen den Frames kein Polling stattfinden kann, würde der NPC davon nichts bemerken. Dies gilt natürlich nur, wenn die Bewegung des Spielers an die Zeit statt an die Framerate gekoppelt ist – bei besonders billigen Spielen wird die Figur einmal pro Frame ein Stück weit bewegt, meist auch direkt abhängig davon, ob eine Pfeiltaste bzw. WASD in diesem Frame gedrückt ist. Kleiner Exkurs: Diese Konstellation ist umso unzuverlässiger, je schneller der Spieler sich bewegt. Angenommen er bewegt sich normalerweise mit 4 Pixeln pro Frame über eine Tile-Map à jeweils 16x16 Pixel, funktioniert das noch ganz gut. Beschleunigt er aber irgendwie auf 32 Pixel pro Frame, würde er einzelne Tiles glatt überspringen, was die Kollisionsabfrage sabotiert.
Zurück zu Endyr, wo oben genannte Lösung nicht nur unzuverlässig sondern unmöglich zu implementieren wäre, denn der Server berechnet keine Frames. Im besten Fall kennt er die Position, wo der Spieler zu Laufen beginnt, und erst wieder die, wo er nach seinem Weg zum Stehen kommt. Ich sage "bester Fall" weil dabei absolut nichts berechnet werden muss, was die Serverauslastung gering hält. Der Server muss dabei nur wissen, wie lange der Spieler für seinen Weg braucht. Ist dieser Zeit abgelaufen, stellt er ihn auf den Zielpunkt und interessiert sich nicht weiter dafür, wo er tatsächlich langgelaufen ist. Aber halt, ermöglicht das kein Cheating? Kurze Antwort: Nein. Der Trick ist, den Weg im Voraus zu prüfen und zu schauen, ob alles seine Richtigkeit hat. Statt also 60x pro Sekunde den Weg häppchenweise abzulaufen und Kollisionen zu testen geschieht das alles in dem Moment, wo der Spieler losläuft. Und hier liegt nun auch der Hund begraben, wenn es darum geht, dass ein NPC den Spieler bemerken soll. Statt dass der NPC Polling betreibt und quasi jeden Schritt des Spielers beobachtet, prüft der Server zu Beginn, ob der Spieler bei einem oder mehreren NPCs vorbeikommt. Falls ja, werden Timer gesetzt und im entsprechenden Moment die NPCs über die Annäherung informiert. Ausser natürlich, der Spieler würde unterwegs eine neue Route einschlagen oder stehen bleiben – in diesem Fall werden alle Timer aktualisiert bzw. entfernt.
Das alles dient freilich nur der Performance – Alternativ kann auch jeder NPC regelmässig (sagen wir gnädigerweise 1x die Sekunde) die Spieler beobachten. Was das "kostet" kann man dabei selbst ausrechnen; angenommen es wuseln 20 Gegner und 3 Spieler im Level herum bedeutet dies 20 Skripts pro Sekunde, von denen jedes eine Schleife mit 3 Spielern abarbeitet bzw. zu jedem die Distanz misst. Polling ist eben teuer. Und damit endet unser kleiner Einblick ins effiziente NPC-Skripting.
Kommentar schreiben