# Cursebreaker Unity Parser A high-performance Rust library for parsing Unity project files (.unity scenes, .prefab prefabs, and .asset files) with automatic MonoBehaviour component discovery and ECS integration. [![Rust](https://img.shields.io/badge/rust-1.70%2B-orange.svg)](https://www.rust-lang.org/) [![License](https://img.shields.io/badge/license-MIT%20OR%20Apache--2.0-blue.svg)](LICENSE) **⚠️ Work in Progress**: This library is under active development. APIs may change. ## Features ### Core Parsing - **Multi-format support**: Parse `.unity` scenes, `.prefab` prefabs, and `.asset` files - **ECS integration**: Automatically builds [Sparsey](https://github.com/LechintanTudor/sparsey) ECS worlds from scenes - **Type-safe**: Strong typing for Unity primitives (Vector3, Quaternion, Color, etc.) - **Fast**: Efficient YAML parsing with minimal allocations ### Component System - **Derive macro**: `#[derive(UnityComponent)]` for automatic component parsing - **Auto-registration**: Components register themselves via [inventory](https://github.com/dtolnay/inventory) - **GUID resolution**: Automatically resolves MonoBehaviour script GUIDs to class names - **Prefab resolution**: Resolves prefab GUIDs for nested prefab references - **Type filtering**: Selectively parse only the components you need ### Advanced Features - **Prefab instantiation**: Clone and modify prefab instances (basic support) - **Reference resolution**: FileID → Entity mapping - **Regex filtering**: Parse only files matching specific patterns - **Transform hierarchies**: Parent-child relationships preserved - **Memory efficient**: 128-bit GUIDs stored as u128 (16 bytes vs ~56 bytes for String) ## Installation Add to your `Cargo.toml`: ```toml [dependencies] unity_parser = { path = "unity-parser" } sparsey = "0.13" # For ECS queries ``` ## Quick Start ### Parse a Unity Scene ```rust use unity_parser::UnityFile; fn main() -> Result<(), Box> { let file = UnityFile::from_path("Scene.unity")?; match file { UnityFile::Scene(scene) => { println!("Scene with {} entities", scene.entity_map.len()); // Query transforms let transforms = scene.world.borrow::(); for (file_id, entity) in &scene.entity_map { if let Some(transform) = transforms.get(*entity) { println!("Entity {} at {:?}", file_id, transform.local_position()); } } } UnityFile::Prefab(prefab) => { println!("Prefab with {} documents", prefab.documents.len()); } UnityFile::Asset(asset) => { println!("Asset with {} documents", asset.documents.len()); } } Ok(()) } ``` ### Parse a Prefab ```rust use unity_parser::UnityFile; fn main() -> Result<(), Box> { let file = UnityFile::from_path("Player.prefab")?; if let UnityFile::Prefab(prefab) = file { // Find all GameObjects let game_objects = prefab.get_documents_by_class("GameObject"); for doc in game_objects { if let Some(mapping) = doc.as_mapping() { if let Some(name) = mapping.get("m_Name").and_then(|v| v.as_str()) { println!("GameObject: {}", name); } } } // Find documents by type ID let transforms = prefab.get_documents_by_type(4); // Transform = type 4 println!("Found {} Transforms", transforms.len()); } Ok(()) } ``` ### Define Custom Components **⚠️ Note**: The derive macro currently has namespace issues and may not compile. Manual implementation is recommended until fixed. ```rust use unity_parser::{UnityComponent, ComponentContext}; use serde_yaml::Mapping; #[derive(Debug, Clone)] pub struct PlaySFX { pub volume: f64, pub start_time: f64, pub end_time: f64, pub is_loop: bool, } // Manual implementation (recommended until macro is fixed) impl UnityComponent for PlaySFX { fn parse(yaml: &Mapping, _ctx: &ComponentContext) -> Option { Some(Self { volume: unity_parser::yaml_helpers::get_f64(yaml, "volume").unwrap_or(1.0), start_time: unity_parser::yaml_helpers::get_f64(yaml, "startTime").unwrap_or(0.0), end_time: unity_parser::yaml_helpers::get_f64(yaml, "endTime").unwrap_or(0.0), is_loop: unity_parser::yaml_helpers::get_bool(yaml, "isLoop").unwrap_or(false), }) } } ``` ## GUID Resolution The parser automatically resolves Unity MonoBehaviour GUIDs to class names: ``` Unity Scene File Rust Code ───────────────── ───────── MonoBehaviour: Custom component m_Script: in ECS World guid: 091c537... ──────────> volume: 1.0 isLoop: 0 ``` ### How It Works 1. **Scan**: Parser scans Unity project's `Assets/` for `*.cs.meta` files 2. **Build Map**: Extracts GUIDs from `.meta` files 3. **Extract Class**: Parses `.cs` files to get `class Name : MonoBehaviour` 4. **Resolve**: Maps GUID → Class Name → Registered Component 5. **Parse**: Automatically parses MonoBehaviour YAML into components The GUID resolver builds automatically when parsing scenes if a Unity project root is detected. ## Type Filtering Parse only specific Unity types and MonoBehaviours for better performance: ```rust use unity_parser::{TypeFilter, parse_unity_file_filtered}; use std::collections::HashSet; // Parse only Transforms and GameObjects let mut types = HashSet::new(); types.insert("Transform".to_string()); types.insert("GameObject".to_string()); let filter = TypeFilter::with_unity_types(types); let file = parse_unity_file_filtered( Path::new("Scene.unity"), None, // No regex filter Some(&filter) )?; ``` ## Regex Path Filtering Parse only files matching specific patterns: ```rust use regex::Regex; use unity_parser::parse_unity_file_filtered; // Only parse production scenes let filter = Regex::new(r"Assets/Scenes/Production/")?; let scene = parse_unity_file_filtered( Path::new("Assets/Scenes/Production/Level1.unity"), Some(&filter), None )?; ``` ## Supported Unity Types ### Built-in Components - ✅ GameObject - ✅ Transform - ✅ RectTransform - ✅ PrefabInstance ### Value Types - ✅ Vector2, Vector3 - ✅ Quaternion - ✅ Color - ✅ FileID, GUID - ✅ ExternalRef, FileRef ### Custom Components - ✅ Any `MonoBehaviour` via manual `UnityComponent` implementation - ⚠️ `#[derive(UnityComponent)]` macro (has namespace bugs, not recommended) ## Architecture ### Component Flow ``` Unity Scene File ↓ Raw YAML Documents ↓ ┌─────────────────────┐ │ GUID Resolution │ ← .meta files + .cs files │ (MonoBehaviour) │ (Script GUID → Class Name) └─────────────────────┘ ↓ ┌─────────────────────┐ │ Prefab GUID Res. │ ← .prefab.meta files │ (Nested Prefabs) │ (Prefab GUID → Prefab Path) └─────────────────────┘ ↓ ┌─────────────────────┐ │ Component Registry │ ← UnityComponent trait impls │ (inventory) │ └─────────────────────┘ ↓ ┌─────────────────────┐ │ ECS World │ ← Sparsey entities & components │ (Transform, etc) │ └─────────────────────┘ ``` ### Memory Efficiency **GUID Storage**: - Old approach: `String` (24 bytes stack + 32 bytes heap = 56 bytes) - Current: `u128` (16 bytes on stack) - **3.5x memory reduction** for GUID storage **GUID Comparison**: - Old: O(n) string comparison (32 characters) - New: O(1) integer comparison - **Significant speedup** for HashMap lookups ## Running Examples ```bash # Parse basic Unity file cargo run --example basic_parsing # Custom component parsing (requires Unity project) cargo run --example custom_component # ECS integration showcase cargo run --example ecs_integration # Find PlaySFX components (requires CBAssets project) cargo run --example find_playsfx ``` ## Testing ```bash # Unit tests cargo test --lib # Integration tests cargo test --test integration_tests # All tests cargo test ``` ## Roadmap ### Completed - ✅ Phase 1: GUID Resolution (Script GUID → Class Name) - ✅ Phase 2: MonoBehaviour Parser - ✅ Phase 3: Prefab GUID Resolution - ✅ Type filtering for selective parsing - ✅ Regex path filtering - ✅ Basic prefab instantiation ### In Progress / Needs Work - 🔧 Refactor `project` module for new architecture - 🔧 Update disabled example/test files - 🔧 Fix example code YAML access patterns ### Future Enhancements - [ ] Full prefab modification system - [ ] Persistent GUID cache for instant loading - [ ] Watch mode for live Unity project monitoring - [ ] More built-in Unity component types - [ ] Better error messages with line numbers - [ ] Parallel processing support - [ ] Cross-platform path handling improvements ## Contributing Contributions welcome! Areas needing help: - **Documentation**: API docs, more examples, tutorials - **Testing**: Integration tests with real Unity projects - **Performance**: Optimize YAML parsing, parallel processing ## Acknowledgments - **Unity Technologies**: For the YAML-based file format - **Sparsey**: ECS library for component storage - **serde_yaml**: YAML parsing foundation - **inventory**: Compile-time component registration