Überblick:
Viele Spiele mit RPG-ähnlichen Statistiken ermöglichen Charakter-"Buffs", die von einfachen "Verursachen von 25% mehr Schaden" bis zu komplizierteren Dingen wie "Verursachen von 15 Schadenspunkten bei Treffern an Angreifer" reichen.
Die Besonderheiten der einzelnen Buff-Typen sind nicht wirklich relevant. Ich suche nach einer (vermutlich objektorientierten) Möglichkeit, mit willkürlichen Buffs umzugehen.
Einzelheiten:
In meinem speziellen Fall habe ich mehrere Charaktere in einer rundenbasierten Kampfumgebung, daher stellte ich mir Buffs vor, die an Ereignisse wie "OnTurnStart", "OnReceiveDamage" usw. gebunden sind. Vielleicht ist jeder Buff eine Unterklasse einer abstrakten Buff-Hauptklasse, in der nur die relevanten Ereignisse sind überladen. Dann könnte jedem Charakter ein Vektor von Buffs zugewiesen werden.
Ist diese Lösung sinnvoll? Ich kann mit Sicherheit feststellen, dass Dutzende von Ereignistypen erforderlich sind. Es fühlt sich so an, als ob eine neue Unterklasse für jeden Buff übertrieben ist und es scheint keine Buff- "Interaktionen" zuzulassen. Das heißt, wenn ich eine Begrenzung für Schadenserhöhungen implementieren wollte, sodass Sie, selbst wenn Sie 10 verschiedene Buffs hatten, die alle 25% zusätzlichen Schaden verursachen, nur 100% anstatt 250% zusätzlichen Schaden verursachen.
Und es gibt kompliziertere Situationen, die ich idealerweise kontrollieren könnte. Ich bin sicher, jeder kann sich Beispiele ausdenken, wie anspruchsvollere Fans möglicherweise auf eine Weise miteinander interagieren können, die ich als Spieleentwickler vielleicht nicht möchte.
Als relativ unerfahrener C ++ - Programmierer (ich habe C im Allgemeinen in eingebetteten Systemen verwendet) halte ich meine Lösung für einfach und nutze die objektorientierte Sprache wahrscheinlich nicht in vollem Umfang aus.
Gedanken? Hat jemand hier schon einmal ein ziemlich robustes Buff-System entworfen?
Bearbeiten: Bezüglich der Antwort (en):
Ich habe eine Antwort ausgewählt, die in erster Linie auf guten Details und einer soliden Antwort auf die von mir gestellte Frage beruhte, aber das Lesen der Antworten gab mir weitere Einblicke.
Vielleicht nicht überraschend, scheinen die verschiedenen Systeme oder optimierten Systeme in bestimmten Situationen besser zu funktionieren. Welches System für mein Spiel am besten funktioniert, hängt von der Art, der Varianz und der Anzahl der Buffs ab, die ich anwenden möchte.
In einem Spiel wie Diablo 3 (siehe unten), in dem fast jede Ausrüstung die Stärke eines Buffs verändern kann, sind die Buffs nur Charakterstatistiken. Ein System scheint eine gute Idee zu sein, wann immer es möglich ist.
Für die rundenbasierte Situation, in der ich mich befinde, ist der ereignisbasierte Ansatz möglicherweise geeigneter.
Auf jeden Fall hoffe ich immer noch, dass jemand mit einer ausgefallenen "OO" -Zauberkugel daherkommt, die es mir ermöglicht, einen Buff von +2 Bewegungsentfernung pro Runde anzuwenden , was 50% des Schadens ausmacht, der dem Buff des Angreifers zugefügt wird, und Ein Spieler teleportiert sich automatisch zu einem nahe gelegenen Plättchen, wenn er von einem Buff mit 3 oder mehr Plättchen Abstand in einem einzigen System angegriffen wird, ohne einen Buff mit +5 Stärke in eine eigene Unterklasse zu verwandeln .
Ich denke, das Nächste ist die Antwort, die ich markiert habe, aber der Boden ist noch offen. Vielen Dank an alle für den Input.
quelle
Antworten:
Dies ist ein kompliziertes Problem, da Sie über einige verschiedene Dinge sprechen, die (heutzutage) als "Buffs" zusammengefasst werden:
Ich implementiere immer die erste mit einer Liste der aktiven Effekte für einen bestimmten Charakter. Das Entfernen von der Liste, ob basierend auf der Dauer oder ausdrücklich, ist ziemlich trivial, daher werde ich das hier nicht behandeln. Jeder Effekt enthält eine Liste von Attributmodifikatoren und kann durch einfache Multiplikation auf den zugrunde liegenden Wert angewendet werden.
Dann wickle ich es mit Funktionen um, um auf die geänderten Attribute zuzugreifen. z.B.:
Auf diese Weise können Sie mühelos multiplikative Effekte anwenden. Wenn Sie auch additive Effekte benötigen, legen Sie fest, in welcher Reihenfolge Sie sie anwenden (wahrscheinlich zuletzt), und durchlaufen Sie die Liste zweimal. (Ich hätte wahrscheinlich separate Modifikatorlisten in Effect, eine für Multiplikative, eine für Additive).
Mit dem Kriterienwert können Sie "+ 20% vs Undead" implementieren. Legen Sie den UNDEAD-Wert für den Effekt fest und übergeben Sie nur den UNDEAD-Wert an
get_current_attribute_value()
wenn Sie einen Schadenswurf gegen einen untoten Gegner berechnen.Übrigens wäre ich nicht versucht, ein System zu schreiben, das Werte direkt auf den zugrunde liegenden Attributwert anwendet und nicht anwendet - das Endergebnis ist, dass Ihre Attribute aufgrund von Fehlern sehr wahrscheinlich vom beabsichtigten Wert abweichen. (Wenn Sie z. B. etwas mit 2 multiplizieren, es dann aber mit einer Kappe abschließen und es erneut durch 2 dividieren, ist es niedriger als es begonnen hat.)
Bei ereignisbasierten Effekten, z. B. "Füge Angreifern bei Treffern 15 Schadenspunkte zu", können Sie Methoden für die Effektklasse hinzufügen. Wenn Sie jedoch ein eindeutiges und willkürliches Verhalten wünschen (z. B. einige Effekte für das oben genannte Ereignis können Schäden widerspiegeln, andere können Sie heilen oder Sie werden zufällig teleportiert, was auch immer), benötigen Sie benutzerdefinierte Funktionen oder Klassen, um damit umzugehen. Sie können Ereignishandlern für den Effekt Funktionen zuweisen und dann die Ereignishandler für alle aktiven Effekte aufrufen.
Natürlich verfügt Ihre Effect-Klasse für jeden Ereignistyp über einen Event-Handler, und Sie können so vielen Handlerfunktionen zuweisen, wie Sie jeweils benötigen. Sie müssen Effect nicht in Unterklassen unterteilen, da jede durch die Zusammensetzung der enthaltenen Attributmodifikatoren und Ereignishandler definiert wird. (Es wird wahrscheinlich auch einen Namen, eine Dauer usw. enthalten.)
quelle
In einem Spiel, an dem ich mit einem Freund für eine Klasse gearbeitet habe, haben wir ein Buff / Debuff-System für den Fall erstellt, dass der Benutzer in hohem Gras gefangen ist und Geschwindigkeitsplättchen hat und was nicht und einige kleinere Dinge wie Blutungen und Gifte.
Die Idee war einfach, und obwohl wir sie in Python angewendet haben, war sie ziemlich effektiv.
Grundsätzlich ist hier, wie es ging:
Wie man nun Buffs aus der ganzen Welt anwendet, ist eine andere Geschichte. Hier ist allerdings mein Anlass zum Nachdenken.
quelle
Ich bin mir nicht sicher, ob Sie das noch lesen, aber ich habe lange mit solchen Problemen zu kämpfen.
Ich habe zahlreiche verschiedene Arten von Affektsystemen entworfen. Ich werde sie jetzt kurz durchgehen. Dies alles basiert auf meinen Erfahrungen. Ich behaupte nicht, alle Antworten zu kennen.
Statische Modifikatoren
Diese Art von System basiert hauptsächlich auf einfachen ganzen Zahlen, um Änderungen zu bestimmen. Zum Beispiel +100 bis max. HP, +10 für Angriffe und so weiter. Dieses System könnte auch Prozente handhaben. Sie müssen nur sicherstellen, dass das Stapeln nicht außer Kontrolle gerät.
Ich habe die generierten Werte für diese Art von System nie wirklich zwischengespeichert. Wenn ich zum Beispiel die maximale Gesundheit von etwas anzeigen möchte, würde ich den Wert sofort generieren. Dies verhinderte, dass die Dinge fehleranfällig und für alle Beteiligten einfacher zu verstehen waren.
(Ich arbeite in Java, daher ist das Folgende Java-basiert, aber es sollte mit einigen Änderungen für andere Sprachen funktionieren.) Dieses System kann leicht mit Aufzählungen für die Änderungstypen und dann mit ganzen Zahlen durchgeführt werden. Das Endergebnis kann in eine Sammlung gestellt werden, die nach Schlüsseln und Werten geordnete Paare enthält. Dies wird eine schnelle Suche und Berechnung sein, so dass die Leistung sehr gut ist.
Insgesamt funktioniert es sehr gut, wenn nur statische Modifikatoren verwendet werden. Code muss jedoch an den richtigen Stellen vorhanden sein, damit die Modifizierer verwendet werden können: getAttack, getMaxHP, getMeleeDamage usw.
Wo diese Methode (für mich) versagt, ist die Interaktion zwischen Buffs sehr komplex. Es gibt keinen wirklich einfachen Weg, um Interaktion zu haben, außer durch ein bisschen Ghetto. Es gibt einige einfache Interaktionsmöglichkeiten. Dazu müssen Sie die Art und Weise ändern, in der Sie die statischen Modifikatoren speichern. Anstatt eine Aufzählung als Schlüssel zu verwenden, verwenden Sie einen String. Diese Zeichenfolge ist der Name der Aufzählung + zusätzliche Variable. 9 Mal von 10 wird die zusätzliche Variable nicht verwendet, daher behalten Sie den Namen der Aufzählung als Schlüssel bei.
Lassen Sie uns ein kurzes Beispiel machen: Wenn Sie in der Lage sein möchten, Schaden an untoten Kreaturen zu ändern, könnten Sie ein geordnetes Paar wie das folgende haben: (DAMAGE_Undead, 10) DAMAGE ist die Aufzählung und Undead ist die zusätzliche Variable. Während Ihres Kampfes können Sie also Folgendes tun:
Wie auch immer, es funktioniert ziemlich gut und ist schnell. Aber es scheitert an komplexen Interaktionen und hat überall "speziellen" Code. Betrachten Sie zum Beispiel die Situation „25% Chance, sich beim Tod zu teleportieren“. Dies ist eine "ziemlich" komplexe. Das obige System kann damit umgehen, aber es ist nicht einfach, da Sie Folgendes benötigen:
Das bringt mich zu meinem nächsten:
Das ultimative komplexe Buff-System
Ich habe einmal versucht, ein 2D-MMORPG selbst zu schreiben. Das war ein schrecklicher Fehler, aber ich habe viel gelernt!
Ich habe das Affektsystem dreimal umgeschrieben. Die erste verwendete eine weniger mächtige Variante der obigen. Der zweite war, worüber ich sprechen werde.
Dieses System hatte eine Reihe von Klassen für jede Modifikation, also Dinge wie: ChangeHP, ChangeMaxHP, ChangeHPByPercent, ChangeMaxByPercent. Ich hatte eine Million dieser Leute - sogar Dinge wie TeleportOnDeath.
Meine Klassen hatten Dinge, die folgendes bewirken würden:
Anwenden und entfernen erklären sich von selbst (obwohl der Affekt bei Dingen wie Prozenten protokollieren würde, um wie viel die HP erhöht wurden, um sicherzustellen, dass der Affekt nachlässt und nur den hinzugefügten Betrag entfernt. Dies war fehlerhaft, lol und Ich habe lange gebraucht, um sicherzugehen, dass es richtig war. Ich habe immer noch kein gutes Gefühl dabei.).
Die checkForInteraction-Methode war ein schrecklich komplexer Code. In jeder der Affects-Klassen (dh ChangeHP) muss der Code festgelegt werden, ob dieser durch den Eingabeeffekt geändert werden soll. Also zum Beispiel, wenn Sie so etwas hatten ...
Die checkForInteraction-Methode würde alle diese Auswirkungen behandeln. Um dies zu tun, musste jeder Effekt auf ALLE Spieler in der Nähe überprüft werden !! Dies ist darauf zurückzuführen, dass ich über einen bestimmten Bereich hinweg mit mehreren Spielern zusammengearbeitet hatte. Dies bedeutet, dass der Code NIEMALS spezielle Aussagen wie oben hatte - "Wenn wir gerade gestorben sind, sollten wir nach Teleportern nach dem Tod suchen". Dieses System würde es automatisch zum richtigen Zeitpunkt richtig handhaben.
Der Versuch, dieses System zu schreiben, dauerte ungefähr 2 Monate und ließ den Kopf mehrmals explodieren. JEDOCH war es WIRKLICH mächtig und konnte unglaublich viel bewirken - besonders wenn man die folgenden zwei Fakten für die Fähigkeiten in meinem Spiel berücksichtigt: 1. Sie hatten Zielbereiche (dh: Single, Self, Group Only, PB AE Self , PB AE-Ziel, zielgerichtete AE und so weiter). 2. Fähigkeiten können mehr als einen Einfluss auf sie haben.
Wie ich oben erwähnte, war dies das 2. oder 3. Affektsystem für dieses Spiel. Warum bin ich davon weggezogen?
Dieses System hatte die schlechteste Leistung, die ich je gesehen habe! Es war furchtbar langsam, da es so viel Zeit in Anspruch nehmen musste, um alles zu überprüfen, was vor sich ging. Ich habe versucht, es zu verbessern, hielt es jedoch für gescheitert.
Also kommen wir zu meiner dritten Version (und einer anderen Art von Buff-System):
Komplexe Affektklasse mit Handlern
Das ist also so ziemlich eine Kombination der ersten beiden: Wir können statische Variablen in einer Affect-Klasse haben, die viele Funktionen und zusätzliche Daten enthält. Rufen Sie dann einfach Handler auf (für mich sind es eher statische Dienstprogrammmethoden als Unterklassen für bestimmte Aktionen. Aber ich bin sicher, Sie können auch Unterklassen für Aktionen verwenden, wenn Sie dies möchten), wenn wir etwas tun möchten.
Die Affekt-Klasse würde alle wichtigen Dinge enthalten, wie Zieltypen, Dauer, Anzahl der Verwendungen, Möglichkeit zur Ausführung und so weiter und so fort.
Wir müssten noch spezielle Codes hinzufügen, um mit den Situationen fertig zu werden, zum Beispiel beim Tod teleportieren. Wir müssten dies immer noch manuell im Kampfcode überprüfen, und wenn es existiert, würden wir eine Liste der Auswirkungen erhalten. Diese Liste der Effekte enthält alle aktuell auf den Spieler angewendeten Effekte, die sich mit dem Teleportieren nach dem Tod befasst haben. Dann schauten wir uns jeden einzelnen an und überprüften, ob er ausgeführt wurde und erfolgreich war (wir hörten beim ersten erfolgreichen auf). Wenn es erfolgreich war, haben wir einfach den Handler angerufen, um dies zu erledigen.
Interaktion kann gemacht werden, wenn Sie auch wollen. Es müsste nur der Code geschrieben werden, um nach bestimmten Stärkungen für die Spieler / etc. Zu suchen. Da es eine gute Leistung hat (siehe unten), sollte es ziemlich effizient sein, dies zu tun. Es würde einfach komplexere Handler und so weiter brauchen.
So hat es eine Menge der Leistung des ersten Systems und immer noch viel Komplexität wie das zweite (aber nicht so viel). Zumindest in Java können Sie einige knifflige Dinge tun, um in den meisten Fällen die Leistung von fast der ersten zu erreichen (z. B .: eine Aufzählungskarte ( http://docs.oracle.com/javase/6/docs/api/java) /util/EnumMap.html ) mit Enums als Schlüsseln und ArrayList von Affects als Werten: So können Sie schnell feststellen, ob Sie Affects haben (da die Liste 0 wäre oder die Map die Enumeration nicht hätte) und nicht Es macht mir nichts aus, über die Affektlisten der Spieler zu iterieren, wenn wir sie zu diesem Zeitpunkt benötigen. Ich optimiere sie später, wenn es zu einem Problem wird.
Ich öffne gerade mein MUD, das im Jahr 2005 endete, erneut (und schreibe das Spiel in Java anstatt in der FastROM-Codebasis, in der es ursprünglich enthalten war). Vor kurzem habe ich festgestellt, wie ich mein Buff-System implementieren möchte. Ich werde dieses System verwenden, weil es in meinem vorherigen fehlgeschlagenen Spiel gut funktioniert hat.
Hoffentlich findet jemand irgendwo ein paar dieser Erkenntnisse nützlich.
quelle
Eine andere Klasse (oder adressierbare Funktion) für jeden Buff ist kein Overkill, wenn sich das Verhalten dieser Buffs voneinander unterscheidet. Eine Sache wäre, + 10% oder + 20% Buffs zu haben (was natürlich besser als zwei Objekte derselben Klasse dargestellt werden würde), die andere wäre, völlig andere Effekte zu implementieren, die ohnehin benutzerdefinierten Code erfordern würden. Ich glaube jedoch, dass es besser ist, Standardmethoden zum Anpassen der Spiellogik zu haben jeden Buff tun zu lassen, was ihm gefällt (und sich möglicherweise auf unvorhergesehene Weise gegenseitig zu stören, wodurch das Gleichgewicht des Spiels gestört wird).
Ich würde vorschlagen, jeden "Angriffszyklus" in Schritte zu unterteilen, wobei jeder Schritt einen Basiswert, eine geordnete Liste von Modifikationen, die auf diesen Wert angewendet werden können (möglicherweise begrenzt), und eine endgültige Obergrenze hat. Jede Änderung hat standardmäßig eine Identitätsumwandlung und kann durch null oder mehr Buffs / Debuffs beeinflusst werden. Die Einzelheiten jeder Modifikation hängen von dem angewendeten Schritt ab. Wie der Zyklus implementiert wird, liegt bei Ihnen (einschließlich der Option einer ereignisgesteuerten Architektur, wie Sie bereits besprochen haben).
Ein Beispiel für einen Angriffszyklus könnte sein:
Das Wichtigste ist, dass je früher im Zyklus ein Buff angewendet wird, desto mehr Wirkung hat er auf das Ergebnis . Wenn Sie also einen "taktischeren" Kampf wollen (bei dem die Spielerfähigkeiten wichtiger sind als die Charakterebene), können Sie viele Buffs / Debuffs für die Basisstatistiken erstellen. Wenn Sie einen "ausgewogeneren" Kampf wollen (bei dem das Level wichtiger ist - wichtig bei MMOGs, um die Fortschrittsrate zu begrenzen), verwenden Sie Buffs / Debuffs erst später im Zyklus.
Die Unterscheidung zwischen "Modifikationen" und "Buffs", die ich zuvor erwähnt habe, hat einen Zweck: Entscheidungen über Regeln und Ausgewogenheit können auf dem ersteren implementiert werden, sodass Änderungen an diesen nicht in Änderungen an jeder Klasse des letzteren berücksichtigt werden müssen. OTOH, die Anzahl und Arten von Buffs sind nur durch Ihre Vorstellungskraft begrenzt, da jeder von ihnen sein gewünschtes Verhalten ausdrücken kann, ohne jegliche mögliche Interaktion zwischen ihnen und den anderen (oder sogar der Existenz anderer überhaupt) berücksichtigen zu müssen.
Beantworten Sie also die Frage: Erstellen Sie keine Klasse für jeden Buff, sondern eine für jede (Art von) Modifikation und binden Sie die Modifikation an den Angriffszyklus und nicht an den Charakter. Die Buffs können einfach eine Liste von (Modifikations-, Schlüssel-, Wert-) Tupeln sein, und Sie können einen Buff auf einen Charakter anwenden, indem Sie ihn einfach zum Buff-Satz des Charakters hinzufügen / daraus entfernen. Dies reduziert auch das Fenster für Fehler, da die Statistiken des Charakters Werte der Stärkungszauber überhaupt nicht geändert werden müssen (so besteht weniger Risiko, dass ein Wert nach Ablauf eines Stärkungszauber auf den falschen Wert zurückgesetzt wird).
quelle
Ich weiß nicht, ob Sie es noch lesen, aber hier ist, wie ich es jetzt mache (Code basiert auf UE4 und C ++). Nachdem ich mehr als zwei Wochen (!!) über das Problem nachgedacht hatte, fand ich schließlich Folgendes:
http://gamedevelopment.tutsplus.com/tutorials/ using-the-composite-design-pattern-for-an-rpg-attributes-system--gamedev-243
Und ich dachte, dass es gar nicht so schlecht ist, ein einzelnes Attribut innerhalb von class / struct zu kapseln. Beachten Sie jedoch, dass ich das in UE4 integrierte Code-Reflektionssystem sehr gut nutzen kann. Ohne einige Nacharbeiten ist dies möglicherweise nicht überall geeignet.
In jedem Fall habe ich damit begonnen, Attribute in eine einzelne Struktur zu packen:
Es ist noch nicht fertig, aber die Grundidee ist, dass diese Struktur ihren internen Zustand verfolgt. Attribute können nur von Effects geändert werden. Der Versuch, sie direkt zu ändern, ist unsicher und für Designer nicht zugänglich. Ich gehe davon aus, dass alles, was mit Attributen interagieren kann, Effekt ist. Einschließlich Pauschalboni von Gegenständen. Wenn ein neuer Gegenstand ausgerüstet ist, wird ein neuer Effekt (zusammen mit dem Griff) erstellt und der speziellen Karte hinzugefügt, die Boni mit unbegrenzter Dauer enthält (die vom Spieler manuell entfernt werden müssen). Wenn ein neuer Effekt angewendet wird, wird ein neues Handle für diesen Effekt erstellt (das Handle ist nur int, umbrochen mit struct). Dieses Handle wird dann als Mittel zur Interaktion mit diesem Effekt herumgereicht und überwacht, ob es sich um einen Effekt handelt immer noch aktiv. Wenn der Effekt entfernt wird, wird sein Handle an alle interessierten Objekte gesendet.
Der wirklich wichtige Teil davon ist TMap (TMap is Hashed Map). FGAModifier ist eine sehr einfache Struktur:
Es enthält die Art der Änderung:
Und Wert, der der endgültige berechnete Wert ist, den wir auf das Attribut anwenden werden.
Wir fügen neue Effekte mit einfachen Funktionen hinzu und rufen dann auf:
Diese Funktion soll den gesamten Bonusstapel neu berechnen, jedes Mal, wenn ein Effekt hinzugefügt oder entfernt wird. Die Funktion ist noch nicht abgeschlossen (wie Sie sehen können), aber Sie können sich einen Überblick verschaffen.
Mein derzeit größter Kritikpunkt ist die Behandlung des Schadens- / Heilungsattributs (ohne dass der gesamte Stapel neu berechnet werden muss). Ich denke, ich habe dies etwas gelöst, aber es sind noch weitere Tests erforderlich, um 100% zu erreichen.
In jedem Fall werden Attribute wie folgt definiert (+ unwirkliche Makros, hier weggelassen):
usw.
Ich bin mir auch nicht 100% sicher, wie ich mit dem Attribut CurrentValue umgehen soll, aber es sollte funktionieren. So wie es jetzt ist.
In jedem Fall hoffe ich, dass es einigen Leuten Kopf-Caches erspart, nicht sicher, ob dies die beste oder sogar gute Lösung ist, aber ich mag es mehr, als Effekte unabhängig von Attributen zu verfolgen. In diesem Fall ist es viel einfacher, für jedes Attribut einen eigenen Status festzulegen, und es sollte weniger fehleranfällig sein. Es gibt im Wesentlichen nur einen Punkt des Scheiterns, der ziemlich kurz und einfach ist.
quelle
Ich habe an einem kleinen MMO gearbeitet und alle Gegenstände, Kräfte, Buffs usw. hatten 'Effekte'. Ein Effekt war eine Klasse, die Variablen für 'AddDefense', 'InstantDamage', 'HealHP' usw. hatte. Die Kräfte, Gegenstände usw. würden die Dauer für diesen Effekt handhaben.
Wenn Sie eine Kraft wirken oder einen Gegenstand aktivieren, wird der Effekt für die angegebene Dauer auf den Charakter angewendet. Dann würden die Hauptangriffs- usw. Berechnungen die angewendeten Effekte berücksichtigen.
Zum Beispiel hast du einen Buff, der die Verteidigung erhöht. Es würde mindestens eine EffectID und eine Duration für diesen Buff geben. Beim Wirken wird die EffectID für die angegebene Dauer auf den Charakter angewendet.
Ein anderes Beispiel für einen Artikel hätte die gleichen Felder. Aber die Dauer wäre unendlich oder bis der Effekt beseitigt ist, indem der Gegenstand aus dem Charakter entfernt wird.
Mit dieser Methode können Sie eine Liste der aktuell angewendeten Effekte durchlaufen.
Hoffe, ich habe diese Methode klar genug erklärt.
quelle
Ich benutze ScriptableOjects als Buffs / Zaubersprüche / Talente
mit UnityEngine; using System.Collections.Generic;
öffentliche Aufzählung BuffType {Buff, Debuff} [System.Serializable] öffentliche Klasse BuffStat {public Stat Stat = Stat.Strength; public float ModValueInPercent = 0.1f; }
BuffModul:
quelle
Dies war eine aktuelle Frage für mich. Ich habe eine Idee dazu.
Buff
Liste und einen Logik-Updater für die Buffs implementieren .Buff
Klasse ändern .Auf diese Weise kann es einfach sein, neue Spielerstatistiken hinzuzufügen, ohne die Logik der
Buff
Unterklassen zu ändern .quelle
Ich weiß, dass dies ziemlich alt ist, aber es wurde in einem neueren Beitrag verlinkt und ich habe einige Gedanken dazu, die ich gerne teilen möchte. Leider habe ich meine Notizen im Moment nicht bei mir, daher versuche ich, einen allgemeinen Überblick über das zu geben, worüber ich spreche, und bearbeite die Details und einige Beispielcodes, wenn ich sie vor mir habe mich.
Erstens denke ich, dass die meisten Leute aus gestalterischer Sicht zu beschäftigt sind, welche Arten von Buffs erstellt werden können und wie sie angewendet werden, und die Grundprinzipien der objektorientierten Programmierung vergessen.
Was meine ich? Es ist eigentlich egal, ob etwas ein Buff oder ein Debuff ist, beide Modifikatoren wirken sich nur positiv oder negativ auf etwas aus . Dem Code ist es egal, welcher welcher ist. Abgesehen davon spielt es letztendlich keine Rolle, ob etwas Statistiken hinzufügt oder multipliziert, das sind nur verschiedene Operatoren, und auch hier ist es dem Code egal, welche welche sind.
Also, wohin gehe ich damit? Dass das Entwerfen einer guten (sprich: einfachen, eleganten) Buff / Debuff-Klasse nicht allzu schwierig ist, liegt daran, die Systeme zu entwerfen, die den Spielstatus berechnen und aufrechterhalten.
Wenn ich ein Buff / Debuff-System entwerfe, würde ich Folgendes in Betracht ziehen:
Einige Besonderheiten, welche Buff / Debuff-Typen enthalten sollten:
Das ist nur ein Anfang, aber von da an definieren Sie einfach, was Sie wollen, und handeln danach unter Verwendung Ihres normalen Spielzustands. Angenommen, Sie möchten einen verfluchten Gegenstand erstellen, der die Bewegungsgeschwindigkeit verringert ...
Solange ich die richtigen Typen eingerichtet habe, ist es einfach, einen Buff-Datensatz zu erstellen, der Folgendes enthält:
Und so weiter, und wenn ich einen Buff erstelle, ordne ich ihm einfach den BuffType of Curse zu und alles andere hängt von der Engine ab ...
quelle