SuraFix Mesh Runtime

Mesh-Optimierung für Unity

Shin Mesh Atlas Tool

Fasst beliebig viele Source-Meshes zu einem einzigen, atlas-texturierten Mesh zusammen — weniger Draw Calls, weniger Materialien, ein Prefab.

Source-Texturen Atlas (Shelf-Pack)
Einzeltexturen Gepackte Slots

Überblick

Das Mesh-Tool kombiniert beliebig viele Kind-Meshes eines Source-Objekts zu einem einzigen Mesh mit einem einzigen Material. Texturen aller Quell-Materialien werden dafür automatisch in einen gemeinsamen Atlas gepackt.

Komponente Rolle
SuraFix_ShinMeshPipelineBuilder Der eigentliche Build-Prozess: sammelt Meshes, packt den Atlas, kombiniert Geometrie, speichert Assets & Prefab.
SuraFix_ShinMeshPipelineWindow Editor-Fenster zur Konfiguration eines Builds (siehe Pipeline-Fenster).
ShinAtlasPacker Eigener Shelf-Pack-Algorithmus für das Texturatlas — Ersatz für Unitys PackTextures().
Shin_AtlasDebugWindow Visualisiert das fertige Atlas-Layout nach einem Build.
SuraFix_ShinInteriorVolume Markiert Bereiche, deren Dreiecke beim Combine entfernt werden sollen (z.B. unsichtbare Innenflächen).
SuraFix_ColliderGrouper Eigenständiges Hilfswerkzeug zum Vorsortieren von Szenen-Objekten vor dem Build.

Workflow

Ein typischer Durchlauf läuft in dieser Reihenfolge:

  1. Objekte in der Szene gruppieren (optional, via Collider Grouper).
  2. Source-Root im Pipeline-Fenster auswählen.
  3. Optional Interior-Volumes platzieren, um unsichtbare Innengeometrie vor dem Build zu entfernen.
  4. Build-Settings einstellen (Atlasgröße, Padding, Mip-Maps, Lightmap-UV2).
  5. Build ausführen — Mesh, Material, Texturen und Prefab landen automatisch im Output-Ordner.
  6. Ergebnis im Atlas Debug Window prüfen.

Schnellstart

Fenster öffnen über:

SuraFix → ShinCore → Mesh Optimizer → Pipeline Builder

Minimal-Konfiguration für einen ersten Test-Build:

var settings = new SuraFix_ShinMeshPipelineBuilder.BuildSettings
{
    SourceRoot = mySceneRoot,
    OutputRootFolder = "Assets/ShinMeshTool",
    AtlasSize = 2048,
    AtlasPadding = 8,
    GenerateLightmapUV2 = true
};

var result = SuraFix_ShinMeshPipelineBuilder.Build(settings);
// result.PrefabPath zeigt auf das fertige, kombinierte Prefab.

1. Sammeln & Vorbereiten

Der Builder durchläuft den SourceRoot rekursiv und sammelt jedes MeshFilter + MeshRenderer-Paar als SourceEntry, zusammen mit der Transform-Matrix relativ zum Root (ToRootLocal) — diese Matrix ist die Grundlage für alle nachfolgenden Positions-, Normalen- und Tangenten-Berechnungen.

Objekte ohne gültiges Mesh oder ohne aktiven Renderer werden automatisch übersprungen, statt den Build abzubrechen.

2. Interior Cutting

Jedes SuraFix_ShinInteriorVolume in CutVolumes definiert eine Box. Liegen alle drei Eckpunkte eines Dreiecks innerhalb eines solchen Volumens, wird das Dreieck beim Combine komplett verworfen.

Das ist gedacht für Innenflächen, die nach dem Zusammenfügen mehrerer Module ohnehin nie sichtbar sind (z.B. doppelte Wandflächen zwischen zwei aneinanderstoßenden Raum-Prefabs) — weniger Dreiecke im Endergebnis, ohne manuell jedes einzelne löschen zu müssen.

Alle-drei-Punkte-Regel: Ein Dreieck, das nur teilweise im Volume liegt, wird nicht geschnitten, sondern komplett behalten. Das Tool schneidet keine Dreiecke an der Volume-Grenze auf — für harte Kanten das Volume entsprechend großzügig oder knapp genug platzieren.

3. Atlas Packing

ShinAtlasPacker ist ein selbst geschriebener Shelf-Pack-Algorithmus: Texturen werden zeilenweise ("Regal für Regal") in den Atlas gelegt. Im Gegensatz zu Unitys eigenem Texture2D.PackTextures() wird dabei keine Textur verworfen — passt etwas nicht, wird die Slot-Größe automatisch halbiert und der Pack-Versuch wiederholt, bis alles passt oder die Mindestgröße von 8px erreicht ist.

Ablauf

  1. Start-Slot-Größe wird aus Atlasgröße und Texturanzahl grob abgeschätzt.
  2. TryPack versucht, alle Texturen bei dieser Slot-Größe unterzubringen.
  3. Scheitert der Versuch, wird die Slot-Größe halbiert und erneut versucht.
  4. Bei Erfolg: Texturen werden per Graphics.Blit auf die Zielgröße skaliert und in den Atlas kopiert.
Schlägt das Packen auch bei 8px Slot-Größe fehl, wirft der Packer eine InvalidOperationException mit der Empfehlung, die Atlasgröße zu erhöhen oder die Mesh-Anzahl zu reduzieren — der Build bricht dann bewusst ab, statt stillschweigend Texturen wegzulassen.

4. Normalen & Tangenten

Beim Zusammenführen werden Positionen, Normalen und Tangenten jedes Source-Vertex korrekt in den Root-Raum transformiert:

Datentyp Transformation
Position ToRootLocal.MultiplyPoint3x4(...)
Normale ToRootLocal.inverse.transpose.MultiplyVector(...) — die inverse Transponierte, nicht die normale Matrix.
Tangente Gleiche inverse Transponierte wie bei Normalen, plus erhaltenes w-Vorzeichen für die Bitangente.
Warum die inverse Transponierte? Eine normale Modell-Matrix verzerrt Normalen falsch, sobald ein Objekt ungleichmäßig skaliert ist (x≠y≠z). Bei reiner Rotation + uniformer Skalierung macht es kaum einen Unterschied — deshalb fällt ein Fehler an dieser Stelle oft erst bei schräg skalierten Objekten auf.

UV-Tiling-Split

Dreiecke, die über UV-Kachelgrenzen hinausragen (z.B. bei wiederholenden Texturen mit Tiling > 1), werden entlang dieser Grenzen automatisch aufgeschnitten, bevor sie ins Atlas-Koordinatensystem übertragen werden — sonst würde ein Dreieck versuchen, über mehrere Atlas-Kacheln gleichzeitig zu samplen.

5. Export & Prefab

Nach erfolgreichem Combine legt der Builder automatisch eine Ordnerstruktur unter OutputRootFolder an:

Assets/ShinMeshTool/
└── <ObjektName>/
    ├── Meshes/<Name>_Combined.asset
    ├── Materials/<Name>_Atlas.mat
    ├── Textures/<Name>_Atlas.png
    ├── Textures/<Name>_NormalAtlas.png   (nur falls Normal Maps vorhanden)
    └── Prefabs/<Name>.prefab

Das fertige Prefab wird automatisch instanziiert, an der ursprünglichen Position/Rotation/Skalierung des Source-Roots platziert und in der Hierarchie ausgewählt — zusammen mit einem automatisch geöffneten Atlas Debug Window zur Kontrolle.

Pipeline-Fenster

Zentrale Editor-UI für einen Build-Durchlauf. Erreichbar über SuraFix → ShinCore → Mesh Optimizer → Pipeline Builder. Stellt alle Felder aus BuildSettings als Inspector-UI bereit, inklusive Drag&Drop für CutVolumes und die SlotOverride-Liste pro Material-Key.

Atlas Debug Window

Öffnet sich automatisch nach einem Build und zeigt das gepackte Atlas-Bild mit eingezeichneten UV-Rects pro Quelltextur — nützlich, um zu prüfen, ob eine Textur unerwartet stark herunterskaliert wurde (sichtbar an einem ungewöhnlich kleinen Slot im Vergleich zu den anderen).

Collider Grouper

Eigenständiges Hilfswerkzeug, unabhängig von der eigentlichen Mesh-Pipeline. Erreichbar über SuraFix → ShinCore → Mesh Optimizer → Collider Grouper.

Findet alle Root-GameObjects einer Szene, deren Position innerhalb eines gewählten Colliders liegt, und verschiebt sie gesammelt unter ein neues Parent-Objekt — Position, Rotation und Skalierung bleiben dabei erhalten. Praktisch, um vor einem Mesh-Combine-Build schnell alle Teile eines Raums unter einen gemeinsamen Root zu sammeln.

Standardmäßig läuft das Tool im Vorschau-Modus (previewOnly) — es zeigt nur, was gefunden wurde, ohne etwas zu verschieben, bis du das explizit deaktivierst.

Interior Volume

SuraFix_ShinInteriorVolume ist eine simple Box-Marker-Komponente ([ExecuteAlways], mit Gizmo-Darstellung in Cyan zur Platzierung im Editor). Sie hat keine Laufzeit-Logik außer der Punkt-in-Box-Prüfung, die vom Mesh-Builder beim Interior Cutting genutzt wird.

Referenz: BuildSettings

Feld Beschreibung
SourceRoot Wurzel-Objekt, dessen Kind-Meshes kombiniert werden.
OutputRootFolder Basis-Pfad für alle erzeugten Assets.
AtlasSize Maximale Kantenlänge des erzeugten Texturatlas in Pixeln.
AtlasPadding Abstand zwischen gepackten Texturen, verhindert Bleeding an Slot-Grenzen.
MaxBakeTextureSize Obergrenze für die Größe, auf die einzelne Texturen vor dem Packen herunterskaliert werden.
UseMipMaps / FilterMode / AnisoLevel Texture-Import-Einstellungen für den fertigen Atlas.
AtlasShaderOverride Optionaler Shader für das erzeugte Material, statt des Standard-Shaders.
GenerateLightmapUV2 Erzeugt eine zweite UV-Kanal für Unitys Lightmap-Baking.
CutVolumes Liste von SuraFix_ShinInteriorVolume-Objekten für das Interior Cutting.
SlotOverrides Pro Material-Key manuell gesetztes Tiling/Offset für Albedo und Normal Map.

Referenz: BuildResult

Feld Beschreibung
PrefabPath / MeshPath / MaterialPath Pfade zu den erzeugten Assets.
TexturePath / NormalTexturePath Pfade zum Albedo- bzw. Normal-Atlas (letzterer nur falls vorhanden).
SourceMeshCount / SourceRendererCount Anzahl der eingesammelten Quell-Meshes bzw. Renderer.
FinalVertexCount Vertexanzahl des kombinierten Meshes nach allen Splits/Cuts.
RemovedTriangleCount Anzahl der durch Interior Cutting entfernten Dreiecke.

FAQ

Mein Build wirft eine InvalidOperationException beim Packen.

Der Atlas konnte selbst bei 8px Slot-Größe nicht alle Texturen unterbringen. AtlasSize erhöhen oder die Anzahl der kombinierten Meshes/Materialien reduzieren.

Ein Innenraum-Dreieck wurde nicht entfernt, obwohl ein Interior Volume dort liegt.

Geprüft wird, ob alle drei Eckpunkte des Dreiecks innerhalb der Box liegen. Liegt nur ein Teil des Dreiecks im Volume, bleibt es vollständig erhalten — Volume entsprechend großzügiger platzieren.

Die Schattierung des kombinierten Meshes sieht anders aus als im Original.

Meist ein Hinweis auf eine fehlerhafte Normalen-Transformation bei nicht-uniform skalierten Source-Objekten. Stelle sicher, dass für Normalen und Tangenten konsequent die inverse Transponierte verwendet wird (siehe Normalen & Tangenten).

SuraFix Shin Mesh Tool — interne Dokumentation