Wie kann ich überprüfen, ob ein Spieler einen Erfolg erzielt hat?

13

Ich mache ein MMO-Spiel und bin gerade an einem Punkt angelangt, an dem ich Erfolge umsetzen muss ... Wie mache ich das? Am einfachsten ist es, dies einmal alle 100 ms auszuführen:

for a in achievements
    for p in players
        if a.meetsRequirements(p) then p.completeAchievement(a)

Das wirft aber noch mehr Komplikationen auf. Wie überprüfe ich beispielsweise, ob der Erfolg tatsächlich abgeschlossen wurde? Haben die Spieler benutzerdefinierte Eigenschaften für einen bestimmten Erfolg? Ich habe so etwas mit Quests gemacht, weil es sich hauptsächlich um "Sammeln von 100 Holz" handelt, also überprüfen aktive Quests eines Spielers dies. Es muss auch einen besseren Zeitpunkt geben, um dies zu überprüfen. Ich denke, dies würde meinen Server regelmäßig verlangsamen.

jcora
quelle
7
Warum nicht einfach relevante Überprüfungen durchführen, während die Aktionen ausgeführt werden? Dh wenn der Benutzer Holz sammelt, prüfen Sie, ob diese der Spezifikation "100 Holz sammeln" entsprechen.
Mike Cluck
1
Das scheint ein bisschen zu chaotisch ... Überall würde es Tonnen von Schecks geben. Ich denke, ich werde mich wegen der Einfachheit an den obigen Algorithmus halten ...
jcora
10
Es gibt Möglichkeiten, es weniger chaotisch zu machen: Wenn Sie beispielsweise einen "OnChange" -Ereignishandler haben, hängen Sie "Leistungsobjekte" an diese an und behandeln die Logik dort. Verstehe auch, dass du mit deinem aktuellen Setup einen Komplexitätsgrad von 0 (n ^ 2) hast, was bedeutet, dass dein Spiel mit mehr Charakteren viel schneller langsamer wird. Ein Problem für ein MMO
Mike Cluck

Antworten:

23

Was Sie tun, hängt von der Art der Leistung ab. Wenn Ihre Erfolge nicht alle einem einfachen Muster entsprechen (X-Anzahl von Ys sammeln), müssen Sie sie bis zu einem gewissen Grad in Sonderfällen auslegen.

Mithilfe eines nachrichtenbasierten Kommunikationssystems können Sie Hooks bereitstellen, mit denen die Sonderfallcodierung lokalisiert wird. Sie können festlegen, dass bestimmte Aktionen Nachrichten an Listener auslösen, die sich selbst registrieren. Dann kann sich Ihr Leistungscode / -skript bei den entsprechenden Zuhörern registrieren und alle erforderlichen Tests durchführen, um die Leistung auszulösen.

Sie hätten Nachrichten zu den typischen Ereignissen, auf die Sie Erfolge hören möchten. Dinge wie "Spieler hat Gegenstand X erworben" oder "Entität Y hat Entität Z getötet". Auf diese Weise können Sie beispielsweise nachverfolgen, wie viele Z der Spieler getötet hat.

Das ist wahrscheinlich das Beste, was Sie für ein Leistungssystem tun können. Es zentralisiert den Code so weit wie möglich und überlässt den Zuhörern die eigentliche Leistungserkennung.

Außerdem sollte beachtet werden, dass bei zentralisierten Leistungssystemen (X-Box Live, Steam-Leistungen) der Fortschritt in Bezug auf Leistungen normalerweise auf dem Server gespeichert wird. Bei Ansammlungserfolgen ("Task XY-Anzahl ausführen") erkennt das Leistungsskript nur, wenn X ausgeführt wurde, und erhöht die Anzahl der Server. Für andere Arten von Erfolgen ("Aufgabe X ausführen") ist die Serverleistung binär: Entweder Sie haben es getan oder Sie haben es nicht getan.

Nicol Bolas
quelle
+1 Das sind großartige Informationen. Auch nützlich, ohne dass ich zum jetzigen Zeitpunkt Erfolge umsetzen muss.
Joshua Hedges
Vielen Dank! Ich kann es kaum erwarten, dies umzusetzen. Ich wünschte, ich hätte diese Idee schon früher ...
jcora
3

Abhängig von der Art Ihrer Erfolge können Sie auch eine Art "Marker-Erfolge" einführen.

Wenn Sie zum Beispiel 3 aufeinanderfolgende Erfolge haben:
Holz 1 - Sammeln Sie 100 Holz
Holz 2 - Sammeln Sie 500 Holz
Holz 3 - Sammeln Sie 1k Holz

Dann wäre es sinnvoll, nur ein OnChange-Ereignis für den ersten Erfolg zu registrieren, bis der Spieler es abgeschlossen hat. Nach Abschluss können Sie das nächste Leistungsobjekt registrieren.

Dies erfordert natürlich das Entwerfen (oder Berechnen) eines Leistungsabhängigkeitsbaums.

Prinz Charles
quelle