somethinglikegames.de
Bluesky Logo

Kategorien


Tags

Eine fiktive Auflistung von Export-Formaten und neben dem Format T3D ist ein Smiley mit hochgezogener Augenbraue

Bevor ich auf das eigentliche Thema zu sprechen komme, möchte ich zuerst erklären, wie dieser Artikel überhaupt entstanden ist.
Ich durfte im Sommersemester 2026 das Wahlfach “Technical Art” im Studiengang “Virtuelle Welten und Game Technologies” an der Hochschule Offenburg unterrichten. Im Laufe der Vorlesung haben wir verschiedene Themen behandelt, die für Technical Artists interessant sein könnten. Als Prüfungsleistung mussten alle Studierenden eine schriftliche Ausarbeitung über ein eigenes Projekt im Kontext Technical Art anfertigen. Die Benotung basierte zwar ausschließlich auf der schriftlichen Dokumentation, ich hatte jedoch angeraten, zusätzlich auch die eigentlichen Projektdateien einzureichen. Falls eine Beschreibung im Text unklar sein sollte, könnte ich so direkt im Projekt nachsehen. Es hat mich wirklich gefreut, wie unterschiedlich die Projekte ausgefallen sind. Von Workflow-Tools bis hin zu Realtime-VFX war alles vertreten. Eines der Projekte, das mit der Unreal Engine umgesetzt wurde, enthielt als Anhang eine Datei mit der Endung .t3d.

T3D 🤨 Dieses Dateiformat war mir bis dahin völlig unbekannt. Eine kurze Recherche ergab, dass T3D früher ein textbasiertes Austauschformat der Unreal Engine war, seit Unreal Engine 4.13 jedoch nicht mehr importiert werden kann. Der Student hatte sein Projekt aber eindeutig mit Unreal Engine 5.7 erstellt. Wie konnte also ein nicht mehr unterstütztes Dateiformat überhaupt exportiert werden? 🤔 Die Antwort ist erstaunlich einfach: Auch aktuelle Versionen der Unreal Engine können zahlreiche Assets weiterhin als T3D exportieren. Man muss lediglich im Content Browser über Asset Actions → Export den Exportdialog öffnen.

Vor einigen Wochen erzählte ich diese Geschichte auf dem GAMESTATE Festival BW einem Gameplay-Programmierer, der sich intensiv mit der Unreal Engine beschäftigt. Seine spontane Reaktion war: “Darüber solltest du einen Artikel schreiben.

Wie ihr seht, habe ich diesen Vorschlag angenommen. Allerdings soll dieser Artikel keine Kritik an einem einzelnen, vergessenen Dateiformat sein.

Denn eigentlich ist T3D gar nicht das Problem.

T3D ist lediglich ein Symptom.

Große Software vergisst

Genau deshalb fand ich den T3D-Fall so interessant. Ein einzelner vergessener Exportdialog ist für sich genommen unproblematisch. Schwierig wird er erst als Hinweis darauf, wie vergesslich große Softwaresysteme mit der Zeit werden. Natürlich nicht im wörtlichen Sinne. Gemeint ist, dass mit jedem neuen Feature, jedem Refactoring und jedem personellen Wechsel ein kleines Stück Kontext verloren geht. Irgendwann weiß niemand mehr, warum bestimmte Teile der Software überhaupt noch existieren.

Unreal Engine ist inzwischen seit Jahrzehnten gewachsen. Unreal Engine 5 entstand nicht vollständig auf der grünen Wiese, sondern entwickelte sich aus Unreal Engine 4, welche wiederum auf Unreal Engine 3 aufbaut. Entsprechend existieren zwangsläufig Komponenten, deren Ursprünge mehr als zehn Jahre zurückreichen. Gleichzeitig veröffentlicht Epic Games mit beeindruckender Geschwindigkeit neue Funktionen. Ein Blick auf die öffentliche Roadmap zeigt, wie viele Features mit jeder Version hinzukommen. Je größer ein System wird, desto schwieriger wird es jedoch, sämtliche Altlasten und historischen Entscheidungen im Blick zu behalten.

Der T3D-Export ist dafür ein passendes Beispiel. Mit Unreal Engine 4.12 führte der Import von T3D-Dateien unter bestimmten Umständen zu einem Absturz des Editors. Die erste Lösung bestand in Unreal Engine 4.13 schlicht darin, T3D im Importdialog nicht länger als auswählbares Dateiformat anzubieten. Über den Dateifilter “*.*” ließ sich der Import allerdings weiterhin erzwingen, inklusive Absturz.

Erst anschließend wurde der Import vollständig deaktiviert. In den Patch Notes heißt es dazu:

The user can no longer attempt to import non-FBX and non-OBJ files when importing into a level.

Im zugehörigen Issue UE-32075 wird zusätzlich erwähnt, dass der Export von T3D-Dateien weiterhin möglich bleibt.

Dieses Issue wurde am 5. Juli 2016 geschlossen. Heute, über zehn Jahre später, gibt es diese Exportfunktion noch immer in Unreal Engine 5.7 und sogar in 5.8. Das eigentliche Problem ist dabei nicht die Exportfunktion selbst. Viel trauriger ist, dass offenbar niemandem mehr auffällt, dass sie überhaupt noch existiert. Genau das ist typisch für große, über viele Jahre gewachsene Softwaresysteme.

Woher ich dieses Muster kenne

Bevor ich mich zunehmend in Richtung Spieleentwicklung orientiert habe, arbeitete ich einige Jahre in der klassischen Softwareentwicklung. Dort war ich Teil eines Teams, das für ein größeres Softwaresystem zuständig war, welches bereits über zehn Jahre existierte, als ich zum Projekt stieß. Von den ursprünglichen Entwicklern arbeitete niemand mehr im Unternehmen. Jedes Teammitglied verantwortete im Durchschnitt etwa 100.000 Zeilen Code. Zwar ist Lines of Code keine sinnvolle Metrik für Komplexität, sie vermittelt aber eine Vorstellung davon, wie groß das System inzwischen geworden war.
Automatisierte Tests waren kaum vorhanden. Die Datenbankschicht basierte noch auf einer Diplomarbeit eines der ursprünglichen Entwickler, weil es zum damaligen Zeitpunkt noch keine etablierten OR-Mapper im Java-Umfeld gab. Also hatte das Team kurzerhand seinen eigenen entwickelt.

Das gesamte Projekt war ein Paradebeispiel für schlecht gealterten Legacy-Code. Jede Änderung barg das Risiko unerwarteter Seiteneffekte. Neue Features dauerten immer länger, weil zunächst verstanden werden musste, welche Auswirkungen eine Änderung an anderer Stelle haben könnte. Irgendwann gelang es uns, das Management davon zu überzeugen, einen Teil unserer Entwicklungskapazitäten gezielt in die technische Modernisierung zu investieren. Über mehrere Jahre hinweg ersetzten wir Schritt für Schritt die problematischsten Bereiche. Der Aufwand war erheblich. Die Ergebnisse allerdings ebenfalls. Mit steigender Softwarequalität sank die Fehlerrate. Gleichzeitig verbesserte sich die Wartbarkeit, und viele Performanceprobleme wurden dabei ebenfalls gelöst.

Technische Schulden sind keine Fehler

Nachdem wir nun gesehen haben, wie selbst ein scheinbar belangloser Exportdialog über Jahre hinweg unbemerkt bestehen bleiben kann, stellt sich die Frage, wie es überhaupt zu solchen Situationen kommt. Eine naheliegende Antwort wäre, dass jemand hat damals einen Fehler gemacht hat. Doch so einfach ist es vermutlich nicht.

In der Softwareentwicklung wird häufig der Ausdruck “technische Schulden” verwendet. Er beschreibt jedoch nicht automatisch schlechten Code, inkompetente Entwickler oder eine misslungene Architektur. Tatsächlich entstehen technische Schulden oft durch völlig nachvollziehbare Entscheidungen.
Stellen wir uns vor, ein Projekt befindet sich kurz vor einem wichtigen Release. Ein neues Feature funktioniert zwar grundsätzlich, müsste aber eigentlich noch einmal sauber überarbeitet werden. Vielleicht fehlt eine automatisierte Testabdeckung, vielleicht müsste eine bestehende Schnittstelle noch einmal grundlegend überdacht werden oder der Code enthält einige unschöne Workarounds. All diese Punkte kosten Zeit. Zeit, die bis zum Release nicht mehr vorhanden ist.
Die Entscheidung lautet dann häufig: Wir bringen das Feature jetzt erst einmal in dieser Form heraus und kümmern uns später darum. Genau in diesem Moment entstehen technische Schulden.

Der Begriff geht auf den Softwareentwickler Ward Cunningham zurück, der ihn bewusst als Analogie zu finanziellen Schulden gewählt hat. Ein Kredit ist schließlich nicht grundsätzlich etwas Schlechtes. Im Gegenteil, dadurch werden Investitionen ermöglicht, die ansonsten vielleicht gar nicht möglich wären. Problematisch wird ein Kredit erst dann, wenn man dauerhaft nur noch die Zinsen bezahlt und die eigentliche Schuld niemals tilgt.
Mit technischen Schulden verhält es sich ganz ähnlich. Kurzfristig können sie eine sinnvolle Entscheidung sein. Ein Spiel muss rechtzeitig erscheinen, ein Kunde wartet auf eine Funktion oder eine Demo soll für eine Messe fertig werden. In solchen Situationen ist es oft vernünftiger, eine pragmatische Lösung zu wählen, als monatelang an der perfekten Architektur zu arbeiten.
Schwierig wird es erst, wenn das Vorhaben, später aufzuräumen, ständig verschoben wird.
Mit jeder weiteren Abkürzung steigt die Komplexität des Systems ein kleines Stück. Neue Entwickler müssen immer mehr historischen Ballast verstehen. Änderungen werden riskanter, weil niemand mehr sicher sagen kann, welche Seiteneffekte sie auslösen. Die Entwicklung neuer Features dauert länger, obwohl das Team eigentlich immer schneller werden wollte.

Genau diese Entwicklung durfte ich in dem Legacy-Projekt erleben, das ich zuvor beschrieben habe. Das System war nicht deshalb schwer wartbar, weil die ursprünglichen Entwickler schlechte Arbeit geleistet hatten. Viele ihrer Entscheidungen waren zum damaligen Zeitpunkt absolut sinnvoll. Das Problem war vielmehr, dass das Projekt über viele Jahre weitergewachsen war, ohne dass ausreichend Zeit investiert wurde, diese Entscheidungen regelmäßig zu hinterfragen und an neue Rahmenbedingungen anzupassen.

Auch der T3D-Export fällt für mich in genau diese Kategorie. Dass diese Exportfunktion heute noch existiert, bedeutet nicht zwangsläufig, dass irgendjemand vor zehn Jahren eine falsche Entscheidung getroffen hat. Vermutlich gab es damals schlicht wichtigere Probleme zu lösen. Interessant ist vielmehr, dass die Funktion zehn Jahre später immer noch vorhanden ist. Nicht, weil sie gebraucht wird, sondern weil offenbar niemand mehr einen Anlass hatte, sie zu entfernen.

Technische Schulden entstehen also nicht in dem Moment, in dem man eine pragmatische Entscheidung trifft. Sie entstehen dann, wenn pragmatische Entscheidungen dauerhaft bestehen bleiben und niemand mehr die Zeit findet, sie wieder zurückzubauen.

Softwarequalität bedeutet mehr als wenige Bugs

Bis hierhin ging es viel um technische Schulden. Doch woran erkennt man eigentlich, dass die Qualität einer Software leidet? Schließlich funktioniert die Unreal Engine hervorragend. Sie rendert beeindruckende Grafiken, bietet unzählige Werkzeuge und wird für Spiele, Filme und Simulationen eingesetzt. Ein vergessener Exportdialog macht sie also nicht plötzlich zu einer schlechten Software.

Warum sollte der T3D-Export dann überhaupt ein Qualitätsproblem sein?
Die Antwort ist, dass Softwarequalität deutlich mehr umfasst als die bloße Abwesenheit von Fehlern. Qualitätsmodelle wie die ISO/IEC 25010 beschreiben verschiedene Eigenschaften, anhand derer sich beurteilen lässt, wie gut eine Software langfristig entwickelt, genutzt und gepflegt werden kann.

Für das T3D-Beispiel sind dabei nicht alle Qualitätsmerkmale gleichermaßen relevant. Im Mittelpunkt steht vor allem die Wartbarkeit. Viele der zuvor beschriebenen Probleme (technische Schulden, Legacy-Code oder vergessene Funktionen) lassen sich letztlich auf dieses eine Qualitätsmerkmal zurückführen.

Wartbarkeit (Maintainability)

Wartbarkeit beschreibt, wie einfach sich eine Software analysieren, verändern und überprüfen lässt. Gerade bei langlebigen Softwaresystemen entscheidet sie darüber, ob neue Anforderungen effizient umgesetzt werden können oder jede Änderung zum Risiko wird.

Versteht heute überhaupt noch jemand dieses Feature?

Der erste Schritt jeder Änderung besteht darin, das bestehende System zu verstehen. Warum existiert eine Funktion? Wer nutzt sie? Welche Komponenten hängen von ihr ab?
Genau diese Fragen lassen sich beim T3D-Export nur schwer beantworten. Ist die Funktion lediglich ein vergessenes Relikt aus Zeiten der Unreal Engine 3 oder gibt es intern noch Werkzeuge oder Workflows, die darauf aufbauen? Ohne dieses Wissen wird bereits die Analyse zu einer Herausforderung.

Die ISO 25010 bezeichnet diese Eigenschaft als Analysierbarkeit (Analysability). Je einfacher sich die Auswirkungen einer Änderung beurteilen lassen, desto besser ist die Wartbarkeit einer Software.

Könnte man den T3D-Export morgen entfernen?

Angenommen, Epic Games würde beschließen, den Export als T3D-Datei in Unreal Engine 5.9 endgültig zu entfernen. Wäre das tatsächlich nur eine kleine Änderung? Vielleicht. Vielleicht aber auch nicht.
Möglicherweise existieren noch Plugins, Build-Pipelines oder interne Werkzeuge, die sich auf genau diese Funktion verlassen. Vielleicht gibt es sogar Nutzer, die den Export zwar nur selten verwenden, aber dennoch darauf angewiesen sind.
Je schwieriger solche Fragen zu beantworten sind, desto riskanter werden selbst kleine Änderungen. Entwickler beginnen, problematische Stellen lieber unangetastet zu lassen, weil niemand sicher vorhersagen kann, welche Seiteneffekte eine Änderung nach sich zieht.

Genau das beschreibt das Untermerkmal Modifizierbarkeit (Modifiability). Gute Software zeichnet sich nicht dadurch aus, dass sie niemals geändert werden muss, sondern dadurch, dass Änderungen mit vertretbarem Aufwand möglich sind.

Woher wüsste man überhaupt, dass nichts kaputtgegangen ist?

Selbst wenn sich der T3D-Export problemlos entfernen ließe, bleibt noch die Frage, wie man herausfindet, ob dadurch nichts anderes beschädigt wird. Existieren automatisierte Tests für diese Funktion? Gibt es Integrations- oder Regressionstests, die mögliche Seiteneffekte erkennen würden? Oder müsste man sich darauf verlassen, dass irgendwann ein Nutzer einen Fehler meldet?

Die ISO 25010 fasst diesen Aspekt unter dem Begriff Testbarkeit (Testability) zusammen. Je einfacher sich Änderungen automatisiert überprüfen lassen, desto geringer ist das Risiko unerwarteter Nebeneffekte.
Gerade in großen Softwaresystemen wird Testbarkeit deshalb zu einem entscheidenden Baustein guter Wartbarkeit.

Benutzbarkeit (Usability)

Softwarequalität betrifft jedoch nicht nur Entwickler, sondern auch ihre Nutzer. Ein Benutzer öffnet den Exportdialog der Unreal Engine und entdeckt dort das Dateiformat T3D. Die naheliegende Annahme lautet: Wenn ich dieses Format exportieren kann, wird es vermutlich auch einen sinnvollen Anwendungsfall dafür geben. Diese Erwartung wird jedoch enttäuscht. Der Import dieses Formats wurde bereits vor über zehn Jahren entfernt.
Der Exportdialog kommuniziert also etwas anderes als das tatsächliche Verhalten der Software. Für erfahrene Unreal-Entwickler mag das lediglich eine kleine Kuriosität sein. Für Einsteiger kann es dagegen unnötige Verwirrung erzeugen.

Benutzbarkeit bedeutet eben nicht nur, dass eine Funktion existiert, sondern auch, dass ihre Bedienung verständlich ist und keine falschen Erwartungen weckt.

Zuverlässigkeit (Reliability)

Auf den ersten Blick scheint Zuverlässigkeit mit dem T3D-Beispiel wenig zu tun zu haben. Schließlich stürzt die Unreal Engine heute durch T3D nicht mehr ab, da ein Import dieses Dateiformats nicht mehr möglich ist. Interessanter wird dieses Qualitätsmerkmal jedoch, wenn man den Blick etwas weiter fasst.
Je schwieriger ein Softwaresystem analysiert, verändert und getestet werden kann, desto vorsichtiger werden seine Entwickler. Refactorings werden verschoben, Altlasten bleiben bestehen und bekannte Probleme werden lieber umgangen als nachhaltig gelöst.
Schlechte Wartbarkeit wirkt sich damit langfristig auch auf die Zuverlässigkeit aus. Denn je schwieriger Änderungen werden, desto größer ist die Wahrscheinlichkeit, dass sich Fehler unbemerkt einschleichen oder bekannte Probleme dauerhaft bestehen bleiben.

Der T3D-Export ist deshalb nicht das eigentliche Problem. Er ist vielmehr ein kleines Symptom dafür, wie schwierig es wird, die Qualität eines Softwaresystems über viele Jahre hinweg auf einem hohen Niveau zu halten.

Der Preis der Vielseitigkeit

Fast jede erfolgreiche Software entwickelt sich im Laufe der Zeit über ihren ursprünglichen Einsatzzweck hinaus. Neue Zielgruppen kommen hinzu, vorhandene Funktionen werden erweitert und gleichzeitig darf möglichst wenig Bestehendes kaputtgehen. Mit jeder dieser Entscheidungen wächst die Komplexität des Systems.

Unreal Engine zeigt diese Entwicklung besonders anschaulich. Ursprünglich als Engine für das Spiel Unreal entwickelt, hat sie sich längst zu einer universellen Plattform verwandelt. Heute kommt sie unter anderem in folgenden Bereichen zum Einsatz:

  • Spieleentwicklung
  • Filmproduktion
  • Virtual Production
  • Architektur und Archviz
  • Automotive
  • UEFN
  • Simulation
  • Digital Twins

Jeder dieser Anwendungsbereiche bringt eigene Anforderungen mit sich. Während für Spieleentwickler vielleicht Verbesserungen an Lumen oder Niagara im Vordergrund stehen, wünschen sich Filmstudios möglicherweise neue Funktionen für die Virtual Production. In der Automobilbranche spielen vermutlich Themen wie CAD-Daten oder hochauflösende Visualisierungen eine größere Rolle. Gleichzeitig erwarten alle Nutzergruppen, dass bestehende Workflows weiterhin funktionieren und sich möglichst wenig an ihren etablierten Prozessen ändert.

Hinzu kommen Anforderungen wie Plugin-Kompatibilität, Abwärtskompatibilität und eine möglichst stabile API. All diese Aspekte sind für sich genommen sinnvoll. Zusammengenommen führen sie jedoch dazu, dass die Software mit jeder Version komplexer wird. Das Entscheidende dabei ist, dass diese Komplexität selten durch eine einzelne große Entscheidung entsteht. Sie wächst schrittweise:

  • Mit jedem neuen Feature
  • Mit jeder zusätzlichen Zielgruppe
  • Mit jeder Entscheidung, bestehendes Verhalten aus Gründen der Kompatibilität beizubehalten

Diese Entwicklung ist keineswegs ungewöhnlich. Sie ist häufig der Preis, den erfolgreiche Software für ihre Vielseitigkeit bezahlt.

Feature-Entwicklung vs. Produktqualität

Neue Features erhöhen idealerweise den Wert eines Produkts. Gleichzeitig erhöht sich dadurch aber ebenfalls fast immer auch die Komplexität.

Stellen wir uns mal zwei Sprint-Reviews vor:

Sprint A:
  • Neues Niagara-Feature
  • Neues Lumen-Feature
  • Neue Animation Nodes
Sprint B:
  • 18.000 Zeilen gelöscht
  • Fünf veraltete APIs entfernt
  • Testabdeckung erhöht
  • Build-Zeit halbiert

Welcher Sprint wirkt beeindruckender? Für die meisten vermutlich Sprint A, dabei kann Sprint B langfristig der wichtigere gewesen sein.

Die eigentliche Erkenntnis

Der T3D-Export ist ein kleines Beispiel für ein Muster, das sich in nahezu jeder langlebigen Software beobachten lässt.

Technische Schulden entstehen selten durch schlechte Entwickler oder falsche Entscheidungen. Meist entstehen sie durch Kompromisse. Ein Feature muss rechtzeitig fertig werden, eine Deadline rückt näher oder eine bereits bestehende Lösung ist gut genug. Problematisch wird es erst, wenn diese Kompromisse nie wieder hinterfragt werden.

Genau deshalb ist Softwarequalität kein Zustand, den man irgendwann erreicht. Sie ist ein fortlaufender Prozess. Alte Entscheidungen müssen regelmäßig überprüft, nicht mehr benötigte Funktionen entfernt und technische Schulden bewusst abgebaut werden. Andernfalls wächst die Komplexität des Systems schleichend weiter, oft so langsam, dass sie erst auffällt, wenn Änderungen plötzlich unverhältnismäßig teuer werden.

Genau hier erinnert Softwareentwicklung an die Broken-Windows-Theorie. Sie besagt vereinfacht, dass kleine Anzeichen von Vernachlässigung weitere Vernachlässigung begünstigen. Übertragen auf Software ist deshalb nicht das einzelne vergessene Feature das Problem, sondern das Signal, das es aussendet. Es zeigt, dass sich offenbar niemand mehr für diesen Teil des Systems verantwortlich fühlt.

Schluss

Das Erstaunliche an der ganzen Geschichte ist eigentlich nicht, dass ein Student versehentlich ein zehn Jahre altes Dateiformat exportiert hat. Er konnte gar nicht wissen, dass dieses Format nicht mehr zurückimportiert werden kann. Überraschend ist vielmehr, dass auch die Engine selbst dieses Wissen im Laufe ihrer Entwicklung offenbar verloren hat.

Ab einer gewissen Größe kämpfen nahezu alle langlebigen Softwaresysteme mit denselben Herausforderungen, unabhängig davon, ob es sich um eine Business-Anwendung, eine Game Engine oder ein Betriebssystem handelt. Da es alle Systeme betreffen kann, gefällt mir deshalb ein Grundsatz aus der Pfadfinderbewegung, den Robert C. Martin in Clean Code auf die Softwareentwicklung übertragen hat:

Leave the campground cleaner than you found it.

Perfektion wird sich in einem großen Softwaresystem kaum erreichen lassen. Aber wenn jeder Entwickler den Code an der Stelle, an der er ohnehin arbeitet, ein kleines Stück besser hinterlässt, als er ihn vorgefunden hat, dann verbessert sich das System mit der Zeit ganz von selbst.

Was bedeutet das nun? Softwarequalität hängt weniger davon ab, ob technische Schulden entstehen, sondern davon, ob wir sie erkennen und bereit sind, sie Schritt für Schritt wieder abzubauen.