Cocos Creator Mini-Spiel-Projektstruktur: Boot, Szenen und Settlement-Seite sauber trennen

Auf dem Bildschirm blinkt „scene not found“ – und plötzlich ist klar: Die Verzeichnisstruktur dieses Mini-Spiel-Projekts ist völlig aus dem Ruder gelaufen.
Vor drei Monaten startete ich voller Zuversicht: Menü eine Szene, Spiel-Hauptansicht eine Szene, Settlement-Seite noch eine – klingt vernünftig, oder? Das Ergebnis: Beim Szenenwechsel verschwanden Spielerpunkte, Loading-Animationen ruckelten wie eine Diashow, und manche Level brauchten 5 Sekunden zum Laden – die Hälfte der Nutzer war weg, bevor überhaupt Gameplay sichtbar wurde.
Erst dann wurde mir klar: Mini-Spiel-Architektur ist nicht einfach ein paar Scene-Dateien übereinanderstapeln. Nach dem Refactoring auf Single-Scene plus vier Layer sank die Ladezeit von 5 auf unter 2 Sekunden, und Szenenwechsel fühlen sich butterweich an.
Warum Mini-Spiele von Single-Scene-Architektur profitieren
Am Anfang habe ich beim Mini-Spiel-Entwickeln kaum an „Architektur“ gedacht. Menü, Spiel, Settlement – jede Oberfläche eine eigene Scene-Datei, simpel und direkt.
In der Praxis tauchen dann mehrere Probleme auf:
Wechsel-Overhead. Bei jedem director.loadScene() zerstört die Engine die alte Szene, baut eine neue auf und lädt Ressourcen neu. Für Mini-Spiele ist das fatal – 53 % der mobilen Nutzer brechen ab, wenn das Laden länger als 3 Sekunden dauert; bei Multi-Scene-Wechseln wird diese Schwelle schnell überschritten.
Zustandsverlust. Der Spieler schließt ein Level mit 1200 Punkten ab, wechselt zur Settlement-Seite – und die Daten sind weg. Warum? Szenenwechsel zerstört alle Nodes, es sei denn, Sie speichern Daten in globalen Variablen oder persistenten Nodes (dazu gleich mehr).
Unterbrochene Animationen. Im Menü läuft noch eine Logo-Animation, der Nutzer tippt auf Start – Szenenwechsel, Animation abgeschnitten. Schlechte UX.
Der Vorteil der Single-Scene-Architektur: Alle UI-Ebenen liegen in derselben Szene. Wechseln heißt nur, das active-Attribut eines Layers zu ändern – kein Zerstören und Neuaufbau, Zustand bleibt erhalten, Animationen laufen weiter. Bei Mini-Spielen mit wenigen Oberflächen reicht das völlig. Große Spiele mit vielen Leveln und großen Assets brauchen Multi-Scene und Subpackages – für Mini-Spiele genügt Single-Scene.
Projektverzeichnis-Vorlage
Wenn der Grund klar ist, folgt die Verzeichnisorganisation.
Das ist die Vorlage, die ich nach mehreren Fehlversuchen für Cocos Creator 3.x zusammengestellt habe:
assets/
├── Scenes/
│ └── Main.scene # Einzige Hauptszene
├── Scripts/
│ ├── managers/
│ │ ├── GameManager.ts # Spielzustand, Datenspeicherung
│ │ ├── UIManager.ts # Layer-Wechsel-Logik
│ │ └── AudioManager.ts # Sound-Verwaltung
│ ├── layers/
│ │ ├── BootLayer.ts # Startseiten-Logik
│ │ ├── MenuLayer.ts # Hauptmenü-Logik
│ │ ├── GameLayer.ts # Spiel-Hauptansicht
│ │ └── SettlementLayer.ts # Settlement-Seite
│ └── components/
│ ├── PlayerController.ts
│ └── EnemyAI.ts
├── Prefabs/
│ ├── UI/
│ │ ├── BootPanel.prefab # Startseiten-UI-Prefab
│ │ ├── MenuPanel.prefab # Menü-UI
│ │ ├── SettlementPanel.prefab
│ ├── Game/
│ │ ├── Player.prefab
│ │ ├── Obstacle.prefab
│ └── Effects/
│ └── Explosion.prefab
├── Resources/
│ ├── textures/ # Dynamisch geladene Bilder
│ ├── audio/ # Sounddateien
│ └── fonts/
└── bundles/ # Asset Bundle Subpackages (WeChat-Optimierung)
├── core/ # Kern-Ressourcenpaket
└── levels/ # Level-Ressourcenpaket
Einige Kernpunkte:
Im Scenes-Verzeichnis liegt nur eine Datei. Main.scene ist die einzige Hauptszene mit Canvas, GameManager und allen Layern. Keine weiteren Scene-Dateien hier ablegen.
managers enthält Verwaltungs-Scripts. GameManager wird per game.addPersistRootNode() persistent und speichert Punkte, Level-Fortschritt usw.; UIManager steuert Layer-Wechsel.
layers enthält die Logik-Scripts je UI-Ebene. Jeder Layer entspricht einem Prefab (unter Prefabs/UI), wird an das Prefab gehängt und unter Canvas in Main.scene platziert.
bundles ist für WeChat-/Douyin-Mini-Spiele gedacht. Erstpaket-Größenlimits gelten; alles über 4 MB lädt per Asset Bundle. Kern-Ressourcen ins core-Bundle, Level-Ressourcen bei Bedarf.
Entspricht Ihre Projektstruktur dem noch nicht, lohnt sich eine Anpassung.
Boot-Szene: Startseite gestalten
Eine Zahl vorweg: Die Cocos Creator Engine selbst ist etwa 1,9 MB groß – plus Ihre Assets sind 3–5 Sekunden First-Screen-Ladezeit normal. Für Mini-Spiele ist das zu lang: Nutzer starren 3 Sekunden auf schwarzen Bildschirm und schließen die App.
Der Boot Layer löst genau das:
Lade-Fortschritt anzeigen. Nutzer sollen sehen, dass geladen wird – nicht, dass die App hängt. Fortschrittsbalken oder Prozent reichen; nicht zu aufwendig, solange Bild-Assets noch laden.
Kern-Ressourcen vorladen. Mit resources.preload() oder Asset Bundle loadBundle() Bilder und Audio für die nächsten Schritte laden.
Markenpräsentation. Logo anzeigen, einfache Animation (z. B. sanftes Einzoomen) – nebenbei Branding.
Ablauf in Kurzform:
Engine-Init → Boot Layer sichtbar → Kern-Ressourcen vorladen → fertig → Wechsel zu MenuLayer
Codebeispiel (BootLayer.ts):
import { _decorator, Component, Node, resources, ProgressBar } from 'cc';
const { ccclass, property } = _decorator;
@ccclass('BootLayer')
export class BootLayer extends Component {
@property(ProgressBar)
progressBar: ProgressBar | null = null;
start() {
// Kern-Assets vorladen
this.preloadCoreAssets();
}
preloadCoreAssets() {
resources.preloadDir('textures', (err, items) => {
if (err) {
console.error('Preload fehlgeschlagen:', err);
return;
}
// Laden abgeschlossen, zum Menü wechseln
this.switchToMenu();
});
}
updateProgress(current: number, total: number) {
if (this.progressBar) {
this.progressBar.progress = current / total;
}
}
switchToMenu() {
// UIManager zum Wechsel zu MenuLayer informieren
// Code folgt weiter unten
}
}
WeChat-Mini-Spiel-Erstpaket-Optimierung: Auf der WeChat-Plattform gilt ein 4-MB-Erstpaket-Limit. Der Rest lädt per Asset Bundle Subpackage. Im Boot Layer können Sie Bundles so laden:
assetManager.loadBundle('levels', (err, bundle) => {
if (err) return;
console.log('Level-Bundle geladen');
});
H5: eigene Startseite: Cocos Creator bietet build-templates für angepasste H5-Startseiten nach dem Build. Im Projektroot build-templates/web-mobile anlegen und eine eigene index.html hinterlegen – statt schwarzem Standard-Screen Loading-Animation oder Markenbild.
Details im offiziellen Forum: Creator | Custom Splash Screen for H5.
Mit dem Boot Layer steht als Nächstes der Kern der Architektur an: wie die vier Layer wechseln.
Vier-Layer-Implementierung: vom Menü zur Settlement-Seite
Das ist der zentrale Teil. Die Hauptszene sieht so aus:
Main.scene
├── Canvas (UI-Container)
│ ├── BootLayer → Lade-Fortschritt, Markenpräsentation
│ ├── MenuLayer → Startbildschirm, Level-Auswahl
│ ├── GameLayer → Spiel-Hauptansicht
│ └── SettlementLayer → Settlement (Punkte, Zeit, Weiter/Retry)
├── GameManager (persistenter Node)
│ └─ speichert: Punkte, Level-Fortschritt, Spielereinstellungen
└── AudioRoot (Audio-Verwaltungs-Node)
Alle vier Layer hängen unter demselben Canvas. Beim Wechsel ändern Sie nur das active-Attribut eines Layers – die anderen bleiben bestehen, Zustand und Animationen bleiben erhalten.
Die Wechsel-Logik liegt im UIManager:
// UIManager.ts
import { _decorator, Component, Node, tween, Vec3 } from 'cc';
const { ccclass, property } = _decorator;
@ccclass('UIManager')
export class UIManager extends Component {
private layers: Map<string, Node> = new Map();
private currentLayer: string = 'BootLayer';
onLoad() {
// Alle Layer-Nodes sammeln
const canvas = this.node.getChildByName('Canvas');
if (!canvas) return;
canvas.children.forEach(child => {
if (child.name.endsWith('Layer')) {
this.layers.set(child.name, child);
child.active = false; // Anfangs alle ausblenden
}
});
// BootLayer anzeigen
this.switchLayer('BootLayer');
}
switchLayer(targetLayer: string) {
// Aktuelle Ebene ausblenden
const current = this.layers.get(this.currentLayer);
if (current) {
current.active = false;
}
// Zielebene einblenden
const target = this.layers.get(targetLayer);
if (target) {
target.active = true;
// Optional: Fade-in-Animation
this.playFadeIn(target);
}
this.currentLayer = targetLayer;
}
playFadeIn(node: Node) {
// Einfache Scale-Fade-in-Animation
node.setScale(new Vec3(0.9, 0.9, 1));
tween(node)
.to(0.2, { scale: new Vec3(1, 1, 1) })
.start();
}
}
Wichtig: Alle Layer-Referenzen in einer Map – beim Wechsel kein wiederholtes getChildByName(), effizienter.
Datenübergabe zur Settlement-Seite: Spieler schließt ein Level mit 1200 Punkten in 45 Sekunden ab – wie kommen die Werte auf die Settlement-Seite?
Antwort: GameManager.
GameManager ist persistent und lebt über das gesamte Spiel. Im GameLayer speichern Sie Punkte und Zeit im GameManager; beim Wechsel zu SettlementLayer lesen Sie sie aus.
// GameManager.ts (vereinfacht)
import { _decorator, Component, game } from 'cc';
const { ccclass, property } = _decorator;
@ccclass('GameManager')
export class GameManager extends Component {
public currentScore: number = 0;
public currentLevel: number = 1;
public playTime: number = 0;
onLoad() {
// Als persistenter Node setzen
game.addPersistRootNode(this.node);
}
// GameLayer ruft diese Methode zum Speichern auf
saveResult(score: number, time: number) {
this.currentScore = score;
this.playTime = time;
}
// SettlementLayer liest mit dieser Methode
getResult() {
return {
score: this.currentScore,
time: this.playTime
};
}
}
Beim Anzeigen der SettlementLayer liest SettlementLayer direkt aus dem GameManager:
// SettlementLayer.ts
onEnable() {
const gameManager = find('GameManager')?.getComponent(GameManager);
if (!gameManager) return;
const result = gameManager.getResult();
this.scoreLabel.string = `Punkte: ${result.score}`;
this.timeLabel.string = `Zeit: ${result.time} Sek.`;
}
Damit ist die Datenübergabe gelöst – ohne komplexes Event-System; GameManager reicht.
Persistente Nodes: datenübergreifende Layer-Kommunikation
Persistente Nodes wurden oben schon erwähnt – hier etwas ausführlicher.
game.addPersistRootNode() ist die offizielle Cocos-Creator-API, damit ein Node beim Szenenwechsel nicht zerstört wird. In Single-Scene wechseln wir keine Szene – warum trotzdem persistente Nodes?
Sie dienen als globales Daten- und Event-Zentrum.
Aufgaben des GameManager:
Spielerdaten speichern – Punkte, Level-Fortschritt, Highscore, freigeschaltete Level.
Einstellungen speichern – Sound, Musik, Sprache.
Globale Events bereitstellen – z. B. „Level abgeschlossen“, auf die Layer hören können.
Hinweise:
Persistente Nodes nicht unter Canvas platzieren. Canvas ist UI-Container und wird beim Umschalten der Layer-active-States mit beeinflusst. Persistente Nodes gehören auf Root-Ebene der Szene.
Manuell anlegen: In Main.scene leeren Node „GameManager“ erstellen, GameManager-Script anhängen, in onLoad() game.addPersistRootNode(this.node) aufrufen.
Sparsam nutzen: Nur wirklich übergreifend benötigte Daten – UI-Zustand eines Layers (z. B. Button-Sichtbarkeit) verwaltet der Layer selbst.
Vollständigeres Datenmodell:
// GameManager.ts (vollständig)
interface PlayerData {
highestScore: number;
unlockedLevels: number[];
currentLevel: number;
}
interface GameSettings {
soundEnabled: boolean;
musicEnabled: boolean;
language: 'zh' | 'en';
}
@ccclass('GameManager')
export class GameManager extends Component {
private playerData: PlayerData = {
highestScore: 0,
unlockedLevels: [1],
currentLevel: 1
};
private settings: GameSettings = {
soundEnabled: true,
musicEnabled: true,
language: 'zh'
};
onLoad() {
game.addPersistRootNode(this.node);
// Daten aus lokalem Speicher laden
this.loadData();
}
loadData() {
const saved = localStorage.getItem('playerData');
if (saved) {
this.playerData = JSON.parse(saved);
}
}
saveData() {
localStorage.setItem('playerData', JSON.stringify(this.playerData));
}
// getters und setters...
}
Hier kommt localStorage zum Persistieren der Spielerdaten hinzu. Mini-Spiel-Plattformen unterstützen localStorage (WeChat nutzt intern wx.setStorageSync; gekapseltes localStorage funktioniert ebenfalls).
Fazit
Zum Abschluss eine Architektur-Checkliste für Ihr Projekt:
Bei Mini-Spielen:
- Single-Scene-Architektur (eine Main.scene)
- Alle UI-Ebenen unter Canvas, Wechsel per Layer
- BootLayer für Lade-Fortschritt und Preloading
- GameManager als persistenter Node für Daten
- Verzeichnisstruktur: assets/Scripts/managers/layers/Prefabs
Bei großen Spielen:
- Multi-Scene sinnvoll (viele Level, große Assets)
- UI-Ebenen können trotzdem Single-Scene + Layer nutzen
- Asset Bundle Subpackages für Ladevorgänge
Diese Architektur habe ich in mehreren Mini-Spiel-Projekten eingesetzt – mit einigen Umwegen, aber inzwischen recht ausgereift. Bei Fragen gerne kommentieren oder ein Beispielprojekt auf GitHub zum Vergleich suchen.
Als Nächstes plane ich Layer-Wechsel-Animationen – Fade, Slide, Scale – damit Übergänge noch flüssiger wirken.
Cocos Creator Single-Scene-Architektur für Mini-Spiele aufsetzen
Von null an Boot-, Hauptszene- und Settlement-Struktur für Mini-Spiele aufbauen
⏱️ Estimated time: 30 min
- 1
Step 1: Projektverzeichnisstruktur anlegen
Unter assets die Verzeichnisse Scenes, Scripts/managers, Scripts/layers, Scripts/components, Prefabs/UI, Prefabs/Game, Resources und bundles anlegen – Dateien nach Verantwortlichkeit trennen. - 2
Step 2: Main.scene und GameManager erstellen
Die einzige Hauptszene Main.scene anlegen, auf Root-Ebene einen GameManager-Node mit Script erstellen und in onLoad() game.addPersistRootNode(this.node) aufrufen, um den Node persistent zu machen. - 3
Step 3: Vier Layer-Prefabs erstellen
Die vier Prefabs BootLayer, MenuLayer, GameLayer und SettlementLayer anlegen, jeweils mit dem passenden Logik-Script versehen und einheitlich unter Prefabs/UI ablegen. - 4
Step 4: UIManager-Wechsel-Logik implementieren
In UIManager.ts alle Layer-Referenzen in einer Map speichern, switchLayer(targetLayer) implementieren und per active-Attribut die Oberfläche wechseln – optional mit Fade-in-Animation. - 5
Step 5: Boot-Layer-Ladeablauf implementieren
In BootLayer.ts resources.preloadDir() für Kern-Assets aufrufen, Fortschrittsbalken aktualisieren und nach Abschluss per UIManager zu MenuLayer wechseln.
FAQ
Warum empfiehlt sich für Mini-Spiele eine Single-Scene-Architektur?
Wie werden Daten beim Szenenwechsel übergeben?
Auf welcher Ebene platziert man persistente Nodes?
Welche Aufgabe hat der Boot Layer?
Was tun, wenn das WeChat-Mini-Spiel-Erstpaket 4 MB überschreitet?
8 Min. Lesezeit · Veröffentlicht am: 19. Mai 2026 · Aktualisiert am: 14. Juli 2026
AI-gestützte Cocos Mini-Game-Entwicklung
Wenn du über die Suche hier gelandet bist, kommst du am schnellsten weiter, indem du zum vorherigen oder nächsten Beitrag dieser Serie springst.
Vorheriger
Indie-Spieleentwicklung: Erst Gameplay validieren, dann Systeme ausbauen (MVP-Praxisleitfaden)
Die größte Falle für Indie-Entwickler beim Mini-Spiel: komplette Systeme bauen und erst dann merken, dass das Gameplay nicht fun. Dieser Leitfaden erklärt den MVP-Validierungspfad – vom Core Loop bis zum Prototyp-Test – und hilft Ihnen, mit minimalem Aufwand zu prüfen, ob sich Ihr Spiel lohnt. Mit Praxisbeispielen und Scheitern.
Teil 2 von 21
Nächster
Mini-Spiel-Zustandsmaschine: Vom Startbildschirm über Kampf bis zur Abrechnung
Dreischichtige Zustandsmaschinen-Architektur für Mini-Spiele – von der Spielfluss-Ebene bis zur Kampf-Detail-Ebene. Mit TypeScript-Schnittstellen, Cocos-Creator-Praxisbeispielen und Lösungen für Zustandsdrift, Parallelitätskonflikte und weitere typische Fallstricke.
Teil 4 von 21
Ähnliche Beiträge
Mini-Spiel-Produktexperiment: Günstiger Validierungspfad für Gameplay und Monetarisierung

Mini-Spiel-Produktexperiment: Günstiger Validierungspfad für Gameplay und Monetarisierung
Mini-Spiel-Ideen mit KI in PRD und Aufgabenliste zerlegen


Kommentare
Melde dich mit GitHub an, um einen Kommentar zu hinterlassen