Grundlagen: Sauberen und robusten Quellcode für dein Spiel entwickeln

Ein Spiel muss noch nicht besonders groß sein, wenn Grundsätze für Ordnung und Übersichtlichkeit nicht eingehalten werden, wird der Quellcode eines Spiels sehr schnell schwer zu durchschauen.

Auch für spätere Erweiterungen sollte einiges beachtet werden. Und besonders wichtig ist natürlich die Stabilität des Spiels. Nachfolgend schauen wir uns die wichtigsten Punkte einmal an.

Der verwendete Beispiel-Code ist in C# für die Unity-Engine geschrieben, kann aber auf andere Sprachen problemlos übertragen werden.

1. Sinnvolle Benennung von Variablen, Methoden und Klassen

Das ist ein ganz logischer Punkt. Natürlich muss ich auch in einer Woche oder einem Monat noch wissen, was bestimmte Variablen machen, was die Aufgabe einer bestimmten Methode ist. Dies gilt insbesondere, wenn mehrere Leute gemeinsam am Projekt arbeiten.

Am besten ist es, dass dies schon aus dem Namen hervorgeht. Auch werden ausführliche Kommentare bei guter Benennung von Variablen, Klassen und Methoden weitgehend überflüssig.

Wie sollte man Variablen, Methoden und Klassen also benennnen?

Im Grunde einfach nur zutreffend. Abkürzungen, die nicht jedem völlig klar sind, sollte man vermeiden.

Auch Ausdrücke wie data, temp, item, group u.ä. scheinen zum Zeitpunkt der Erstellung völlig klar und logisch, kurze Zeit später aber schon nicht mehr. Welche Daten meint data dann? Gespeicherte Daten, Spielerdaten oder was?

Also im Zweifel besser etwas ausführlichere Namen verwenden. Hier ein positives und ein negatives Beispiele für Variablen und Klassennamen.


Bei Methodennamen sollte aus dem Namen schon hervorgehen was die Methode macht und ggf. was sie zurückgibt. Auch hier ein Beispiel.


Werbung (Affiliate - ich bekomme eine kleine Provision, dein Preis ändert sich nicht)


2. Quellcode immer fokussiert halten

Klassen und Methoden sollten immer nur eine jeweilige Aufgabe haben und sich nicht um verschiedene Dinge kümmern.

Wenn also eine Methode GetPlayerPosition() heißt, gibt sie eben nur die Position des Spielers zurück. Die Methode sollte den Spieler nicht noch versetzen, falls er sich zu nah am Spielfeldrand befindet.


Bei Klassen ganz genauso. Soll eine Klasse sich nur um das Speichern und Laden von Daten kümmern, macht sie auch nur das. Sie sollte nicht noch prüfen, ob der Spieler schon das Ende des Levels erreicht hat, alle Feinde tot sind und nur dann speichern.

3. Einfache und klar lesbare Lösungen suchen

Quellcode sollte klar, einfach und verständlich verfasst werden. Lösungen, mit vielen Einschränkungen und Workarounds bringen nur Chaos in den Quellcode.

Oft hilft es komplizierte Vorgänge, mit Hilfe von zusätzlichen Methoden, in leichter überschaubare Stücke zu brechen.

Auch die durchdachte Verwendung geeigneter Datentypen kann einiges einfacher machen.


Auch zusätzliche Variablen können den Code klarer und besser lesbar machen.


4. Gültigkeit von Referenzen und Werten prüfen

Wenn zur Laufzeit Daten bezogen werden, ob aus eigenen Klassen oder aus Klassen, die die Engine bietet, sollten die Werte und Referenzen vor der Verwendung immer geprüft werden.

Dies kann auf unterschiedliche Arten passieren. Die Unity Engine zum Beispiel bietet dafür auch Methoden an. Komponenten, die nicht ganz sicher vorhanden sind (z.B. bei der Auswertung von Kollisionen), holt man besser mit TryGetComponent() statt mit GetComponent. Alternativ könnte auch auf null geprüft werden, bevor die Variable verwendet wird.


Auch Werte sollte man vor der Verwendungen im Zweifel besser prüfen. So könnte man z.B. den eingehenden Anzeigewert eines Tachos vorher prüfen und sonst nicht anzeigen.


Im obigen Beispiel könnte man sich auch dazu entscheiden, den eingehenden Wert einfach zu begrenzen.


Überhaupt sollten Variablen, wie im obigen Beispiel, nur über dafür vorgesehene Schnittstellen beeinflusst werden. Dazu mehr unter Punkt 6.

5. Zustände und Fehler in der Konsole ausgeben

Zur leichteren Fehlersuche sollten regelmäßig Meldungen in der Konsole ausgegeben werden, darüber was gerade bearbeitet wurde und mit welchem Ergebnis. Nachfolgend ein einfaches Beispiel.


Auch Fehlermeldungen sollte man wenn nötig ausgeben. Das Tacho-Beispiel von Punkt 4 verheimlicht, wenn ein angenommener Wert ausserhalb des Anzeigebereichs liegt. Da dies aber ein Fehler ist, sollte er auch als solches ausgegeben werden.

6. Kapselung strikt einhalten

Das Konzept der Kapselung ist grundlegend in der objektorientierten Programmierung. Das heißt, es sollte keine öffentlichen Felder geben, auch in Unity nicht. Dort sieht man häufig, dass alles was im Inspector angezeigt werden soll, einfach als public deklariert wird.

Das ist aber nicht nötig, denn es gibt das [SerializeField] Attribut, um auch private Felder im Inspector anzuzeigen.

Variablen anderer Klassen sollten also nur über Methoden oder Properties durch andere Klassen beeinflusst werden. Sinn der Sache ist, klare Schnittstellen zwischen den Klassen zu schaffen. Dies erhöht die Wartbarkeit, Stabilität und Übersicht, ausserdem erleichtert es die Fehlersuche. Nachfolgend die beiden Möglichkeiten.

7. Nicht durch mehrere Klassen greifen

Das Durchgreifen über mehrere Klassen hinweg, evtl. sogar mittels Arrays oder Listen, sollte man vermeiden. Es trägt nachvollziehbar nicht zur Übersicht bei.

8. Events bringen Ordnung und Skalierbarkeit

Events, egal ob System-Events (z.b. Action) oder UnityEvents, sind sehr praktisch. Anstatt deine Klassen fest per Methodenaufruf zu verbinden und Daten so auszutauschen, solltest Du möglichst oft Events verwenden.

So vermeidest Du Abhängigkeiten und kannst dein Programm auf jeden Fall immer sehr einfach vergrößern oder verkleinern. Ohne dass Du durch Abhängigkeiten Probleme bekommst.

Hier findest Du mir Infos zu Events

9. Fazit

Sicher gibt es noch weitere Maßnahmen, die zur Übersicht, Wartbarkeit, Skalierbarkeit und Stabilität beitragen. Es geht hier aber um die Grundlagen. Wenn Du diese Punkte einigermaßen beachtest, kannst Du dein eigenes Spiel gut fertig stellen und irgendwann problemlos erweitern, ohne zu verzweifeln. Viel Erfolg!