prefab spawning bugfix

This commit is contained in:
2026-01-05 12:23:09 +00:00
parent dea28f5b9c
commit 0f2cb68fa4
9 changed files with 91 additions and 833 deletions

View File

@@ -12,7 +12,9 @@
"Bash(ls:*)", "Bash(ls:*)",
"Bash(find:*)", "Bash(find:*)",
"Bash(grep:*)", "Bash(grep:*)",
"Bash(wc:*)" "Bash(wc:*)",
"Bash(pgrep:*)",
"Bash(cargo doc:*)"
], ],
"additionalDirectories": [ "additionalDirectories": [
"/home/connor/repos/CBAssets/" "/home/connor/repos/CBAssets/"

View File

@@ -253,78 +253,6 @@ Raw YAML Documents
- New: O(1) integer comparison - New: O(1) integer comparison
- **Significant speedup** for HashMap lookups - **Significant speedup** for HashMap lookups
## Project Structure
```
cursebreaker-parser-rust/
├── unity-parser/ # Main library crate
│ ├── src/
│ │ ├── ecs/ # ECS world building
│ │ │ └── builder.rs
│ │ ├── model/ # UnityFile, Scene, Prefab, Asset
│ │ │ └── mod.rs
│ │ ├── parser/ # YAML parsing & GUID resolution
│ │ │ ├── guid_resolver.rs # Script GUID → Class Name
│ │ │ ├── prefab_guid_resolver.rs # Prefab GUID → Path
│ │ │ ├── meta.rs # .meta file parsing
│ │ │ ├── yaml.rs # YAML document splitting
│ │ │ └── mod.rs
│ │ ├── project/ # ⚠️ OUTDATED - needs refactoring
│ │ │ └── mod.rs
│ │ ├── types/ # Unity types & components
│ │ │ ├── unity_types/
│ │ │ │ ├── game_object.rs
│ │ │ │ ├── transform.rs
│ │ │ │ ├── prefab_instance.rs
│ │ │ │ └── mod.rs
│ │ │ ├── component.rs # UnityComponent trait & helpers
│ │ │ ├── guid.rs # 128-bit GUID type
│ │ │ ├── ids.rs # FileID, LocalID
│ │ │ ├── reference.rs # UnityReference enum
│ │ │ ├── type_filter.rs # TypeFilter for selective parsing
│ │ │ ├── values.rs # Vector3, Quaternion, Color, etc.
│ │ │ └── mod.rs
│ │ ├── error.rs # Error types
│ │ ├── macros.rs
│ │ ├── property/
│ │ └── lib.rs
│ ├── examples/
│ │ ├── basic_parsing.rs
│ │ ├── custom_component.rs
│ │ ├── ecs_integration.rs
│ │ ├── find_playsfx.rs
│ │ ├── parse_resources.rs
│ │ └── parse_resource_prefabs.rs
│ ├── tests/
│ └── Cargo.toml
├── unity-parser-macros/ # Proc macro crate (⚠️ has bugs)
│ ├── src/
│ │ └── lib.rs
│ └── Cargo.toml
├── Cargo.toml # Workspace config
└── README.md
```
## Known Issues
### Critical Issues
1. **`unity-parser/src/project/mod.rs` is OUTDATED**
- Built for old architecture before `UnityFile` enum refactor
- References non-existent `UnityDocument` type (should be `RawDocument`)
- Module is disabled in lib.rs until refactored
2. **Derive macro namespace mismatch**
- `unity-parser-macros` uses `unity_parser` namespace
- Actual crate name is `unity_parser::` (underscore, not hyphen)
- Manual `UnityComponent` implementation recommended
3. **Placeholder values in Cargo.toml**
- Author and repository fields need updating
### Minor Issues
1. Disabled example/test files may reference outdated APIs
2. Some examples may have incorrect YAML access patterns
## Running Examples ## Running Examples
```bash ```bash
@@ -386,15 +314,6 @@ Contributions welcome! Areas needing help:
- **Testing**: Integration tests with real Unity projects - **Testing**: Integration tests with real Unity projects
- **Performance**: Optimize YAML parsing, parallel processing - **Performance**: Optimize YAML parsing, parallel processing
## License
Licensed under either of:
- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
at your option.
## Acknowledgments ## Acknowledgments
- **Unity Technologies**: For the YAML-based file format - **Unity Technologies**: For the YAML-based file format

View File

@@ -14,7 +14,7 @@ use std::fs::File;
use std::io::Write; use std::io::Write;
use std::path::Path; use std::path::Path;
use unity_parser::log::DedupLogger; use unity_parser::log::DedupLogger;
use log::{info, warn, error, LevelFilter}; use log::{info, error, LevelFilter};
fn main() -> Result<(), Box<dyn std::error::Error>> { fn main() -> Result<(), Box<dyn std::error::Error>> {
@@ -36,6 +36,8 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let scene_path = "_GameAssets/Scenes/Tiles/10_3.unity"; let scene_path = "_GameAssets/Scenes/Tiles/10_3.unity";
info!("📁 Parsing scene: {}", scene_path); info!("📁 Parsing scene: {}", scene_path);
log::logger().flush();
// Parse the scene using the project // Parse the scene using the project
match project.parse_scene(scene_path) { match project.parse_scene(scene_path) {
Ok(scene) => { Ok(scene) => {
@@ -47,6 +49,23 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let transform_view = scene.world.borrow::<unity_parser::Transform>(); let transform_view = scene.world.borrow::<unity_parser::Transform>();
let gameobject_view = scene.world.borrow::<unity_parser::GameObject>(); let gameobject_view = scene.world.borrow::<unity_parser::GameObject>();
info!("DEBUG: entity_map size: {}", scene.entity_map.len());
info!("DEBUG: Checking world for InteractableResource components...");
// Check how many entities in entity_map have the component
let mut entities_in_map_with_resource = 0;
for entity in scene.entity_map.values() {
if resource_view.contains(*entity) {
entities_in_map_with_resource += 1;
if entities_in_map_with_resource <= 5 { // Only log first 5
if let Some(resource) = resource_view.get(*entity) {
info!("DEBUG: Entity {:?} in entity_map has InteractableResource, typeId: {}", entity, resource.type_id);
}
}
}
}
info!("DEBUG: Entities in entity_map with InteractableResource: {}", entities_in_map_with_resource);
// Find all entities that have Interactable_Resource // Find all entities that have Interactable_Resource
let mut found_resources = Vec::new(); let mut found_resources = Vec::new();
@@ -68,6 +87,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
} }
info!("🔍 Found {} Interactable_Resource component(s)", found_resources.len()); info!("🔍 Found {} Interactable_Resource component(s)", found_resources.len());
log::logger().flush();
if !found_resources.is_empty() { if !found_resources.is_empty() {
// Display resources in console // Display resources in console

View File

@@ -1,693 +0,0 @@
Cursebreaker Resource Prefabs
======================================================================
Total resources found: 171
----------------------------------------------------------------------
Prefab: HarvestableSpawner_73Medicinal Herbs
TypeID: 73
MaxHealth: 0
Prefab: HarvestableSpawner_65Radishes
TypeID: 65
MaxHealth: 0
Prefab: HarvestableSpawner_22Sandstone Grouper
TypeID: 22
MaxHealth: 0
Prefab: HarvestableSpawner_14Mageflower
TypeID: 14
MaxHealth: 0
Prefab: HarvestableSpawner_108mountain Ore3
TypeID: 108
MaxHealth: 0
Prefab: HarvestableSpawner_120Swamp Brambles
TypeID: 120
MaxHealth: 0
Prefab: HarvestableSpawner_20Caveshroom
TypeID: 20
MaxHealth: 0
Prefab: Prefab_Resource_30HeartbellVine
TypeID: 30
MaxHealth: 5
Prefab: HarvestableSpawner_76Speed herb
TypeID: 76
MaxHealth: 0
Prefab: Prefab_Resource_22SandstoneGrouper
TypeID: 22
MaxHealth: 5
Prefab: Prefab_Resource_64Carrot_Field
TypeID: 64
MaxHealth: 5
Prefab: HarvestableSpawner_26Betta Iotachi
TypeID: 26
MaxHealth: 0
Prefab: HarvestableSpawner_85Magic res ampoule crafting mat
TypeID: 85
MaxHealth: 0
Prefab: Prefab_Resource_15Blueberries
TypeID: 15
MaxHealth: 5
Prefab: HarvestableSpawner_58Radiant Sunflower
TypeID: 58
MaxHealth: 0
Prefab: HarvestableSpawner_76Waspheart Iris
TypeID: 76
MaxHealth: 0
Prefab: HarvestableSpawner_30Heartbell Vine
TypeID: 30
MaxHealth: 0
Prefab: HarvestableSpawner_61Eggplants
TypeID: 61
MaxHealth: 0
Prefab: Prefab_Resource_8Deadwood
TypeID: 0
MaxHealth: 5
Prefab: HarvestableSpawner_70Cabbage
TypeID: 70
MaxHealth: 0
Prefab: Prefab_Resource_19Coal
TypeID: 19
MaxHealth: 20
Prefab: Prefab_Resource_12PebbleSturgeon
TypeID: 12
MaxHealth: 5
Prefab: Prefab_Resource_6Oak
TypeID: 6
MaxHealth: 5
Prefab: HarvestableSpawner_2Copper Ore
TypeID: 2
MaxHealth: 0
Prefab: HarvestableSpawner_111Deep Earth Moss
TypeID: 111
MaxHealth: 0
Prefab: HarvestableSpawner_49Dreamylion
TypeID: 49
MaxHealth: 0
Prefab: HarvestableSpawner_71Nest
TypeID: 71
MaxHealth: 0
Prefab: HarvestableSpawner_19Coal
TypeID: 19
MaxHealth: 0
Prefab: Prefab_Resource_21CharcoalSnapper
TypeID: 21
MaxHealth: 5
Prefab: HarvestableSpawner_12Pebble Sturgeon
TypeID: 12
MaxHealth: 0
Prefab: Prefab_Resource_25ObsidianWalleye
TypeID: 25
MaxHealth: 5
Prefab: Prefab_Resource_65Radish_Field
TypeID: 65
MaxHealth: 5
Prefab: HarvestableSpawner_83Phys res ampoule crafting mat
TypeID: 83
MaxHealth: 0
Prefab: HarvestableSpawner_78Firestick flower
TypeID: 78
MaxHealth: 0
Prefab: Prefab_Resource_13ArcaneSeedTree
TypeID: 13
MaxHealth: 5
Prefab: HarvestableSpawner_116Tree
TypeID: 116
MaxHealth: 0
Prefab: HarvestableSpawner_6Oak
TypeID: 6
MaxHealth: 0
Prefab: HarvestableSpawner_37Ancients' Tears
TypeID: 37
MaxHealth: 0
Prefab: HarvestableSpawner_63Corn
TypeID: 63
MaxHealth: 0
Prefab: HarvestableSpawner_44Voidlight Tendril
TypeID: 44
MaxHealth: 0
Prefab: Prefab_Resource_5TitaniumOre
TypeID: 5
MaxHealth: 20
Prefab: HarvestableSpawner_55Poppy of the Fallen
TypeID: 55
MaxHealth: 0
Prefab: HarvestableSpawner_102mountain fish3
TypeID: 102
MaxHealth: 0
Prefab: HarvestableSpawner_15Blueberries
TypeID: 15
MaxHealth: 0
Prefab: HarvestableSpawner_41Falls Hydrangea
TypeID: 41
MaxHealth: 0
Prefab: Prefab_Resource_26BettaIotachi
TypeID: 26
MaxHealth: 5
Prefab: Prefab_Resource_36Noblerose
TypeID: 36
MaxHealth: 5
Prefab: Prefab_Resource_58Sunflower
TypeID: 58
MaxHealth: 5
Prefab: HarvestableSpawner_45Autumnleaf Lily
TypeID: 45
MaxHealth: 0
Prefab: Prefab_Resource_32Lakesberry
TypeID: 32
MaxHealth: 5
Prefab: HarvestableSpawner_106Imberite Ore
TypeID: 106
MaxHealth: 0
Prefab: HarvestableSpawner_100mountain fish1
TypeID: 100
MaxHealth: 0
Prefab: HarvestableSpawner_27Rock Lobster
TypeID: 27
MaxHealth: 0
Prefab: HarvestableSpawner_9Wild Goopy
TypeID: 9
MaxHealth: 0
Prefab: HarvestableSpawner_68Epic ore
TypeID: 68
MaxHealth: 0
Prefab: HarvestableSpawner_113Soulgrowth Mushrooms
TypeID: 113
MaxHealth: 0
Prefab: HarvestableSpawner_28Horsetail Reed Bass
TypeID: 28
MaxHealth: 0
Prefab: HarvestableSpawner_8Deadwood tree
TypeID: 8
MaxHealth: 0
Prefab: HarvestableSpawner_77Glowing Willow
TypeID: 77
MaxHealth: 0
Prefab: Prefab_Resource_33Silvermirror
TypeID: 33
MaxHealth: 5
Prefab: HarvestableSpawner_42Wight's Pearls
TypeID: 42
MaxHealth: 0
Prefab: HarvestableSpawner_16Spellbound Oak
TypeID: 16
MaxHealth: 0
Prefab: HarvestableSpawner_25Obsidian Walleye
TypeID: 25
MaxHealth: 0
Prefab: Prefab_Resource_50Haniflower
TypeID: 50
MaxHealth: 5
Prefab: Prefab_Resource_2CopperOre
TypeID: 2
MaxHealth: 20
Prefab: HarvestableSpawner_64Carrots
TypeID: 64
MaxHealth: 0
Prefab: HarvestableSpawner_32Lakesberry
TypeID: 32
MaxHealth: 0
Prefab: HarvestableSpawner_115Malicious Sporecap
TypeID: 115
MaxHealth: 0
Prefab: HarvestableSpawner_88Saltpeter Mine
TypeID: 88
MaxHealth: 0
Prefab: Prefab_Resource_23FuchsiaPerch
TypeID: 23
MaxHealth: 5
Prefab: Prefab_Resource_54GoldenSunflower
TypeID: 54
MaxHealth: 5
Prefab: HarvestableSpawner_58Sunflower
TypeID: 58
MaxHealth: 0
Prefab: HarvestableSpawner_117Ore
TypeID: 117
MaxHealth: 0
Prefab: HarvestableSpawner_1Spruce
TypeID: 1
MaxHealth: 0
Prefab: HarvestableSpawner_79Minigame tree
TypeID: 79
MaxHealth: 0
Prefab: HarvestableSpawner_7Evark tree
TypeID: 7
MaxHealth: 0
Prefab: HarvestableSpawner_81Puppet Flower
TypeID: 81
MaxHealth: 0
Prefab: HarvestableSpawner_6Oak tree
TypeID: 6
MaxHealth: 0
Prefab: Prefab_Resource_14Mageflower
TypeID: 14
MaxHealth: 5
Prefab: Prefab_Resource_7Evark
TypeID: 0
MaxHealth: 5
Prefab: HarvestableSpawner_86Generic mining
TypeID: 86
MaxHealth: 0
Prefab: HarvestableSpawner_85Darkmire Damp Root
TypeID: 85
MaxHealth: 0
Prefab: HarvestableSpawner_110Crystalvein Rose
TypeID: 110
MaxHealth: 0
Prefab: HarvestableSpawner_4Imberite ore
TypeID: 4
MaxHealth: 0
Prefab: Prefab_Resource_16SpellboundOak
TypeID: 16
MaxHealth: 5
Prefab: HarvestableSpawner_59Evening's Cup
TypeID: 59
MaxHealth: 0
Prefab: Prefab_Resource_38Dandelions
TypeID: 38
MaxHealth: 5
Prefab: HarvestableSpawner_101mountain fish2
TypeID: 101
MaxHealth: 0
Prefab: HarvestableSpawner_115MaliciousSporecap
TypeID: 115
MaxHealth: 0
Prefab: HarvestableSpawner_43Skyfold Flower
TypeID: 43
MaxHealth: 0
Prefab: HarvestableSpawner_67Cotton
TypeID: 67
MaxHealth: 0
Prefab: HarvestableSpawner_84Ranged res ampoule crafting mat
TypeID: 84
MaxHealth: 0
Prefab: HarvestableSpawner_23Fuchsia Perch
TypeID: 23
MaxHealth: 0
Prefab: HarvestableSpawner_84Marshland Feather Reed
TypeID: 84
MaxHealth: 0
Prefab: Prefab_Resource_24GoblinShad
TypeID: 24
MaxHealth: 5
Prefab: HarvestableSpawner_109mountain herb1
TypeID: 109
MaxHealth: 0
Prefab: HarvestableSpawner_35Red Nymph
TypeID: 35
MaxHealth: 0
Prefab: HarvestableSpawner_80Sunburst Marlin
TypeID: 80
MaxHealth: 0
Prefab: HarvestableSpawner_74Soothing Mallow
TypeID: 74
MaxHealth: 0
Prefab: HarvestableSpawner_60Golden Tulip
TypeID: 60
MaxHealth: 0
Prefab: HarvestableSpawner_114ColdwaterLily
TypeID: 114
MaxHealth: 0
Prefab: HarvestableSpawner_24Goblin Shad
TypeID: 24
MaxHealth: 0
Prefab: HarvestableSpawner_46Cloud Yarrow
TypeID: 46
MaxHealth: 0
Prefab: HarvestableSpawner_113SoulgrowthMushroom
TypeID: 113
MaxHealth: 0
Prefab: HarvestableSpawner_104mountain tree2
TypeID: 104
MaxHealth: 0
Prefab: Prefab_Resource_62Chili_Pepper_Field
TypeID: 62
MaxHealth: 5
Prefab: Prefab_Resource_67Cotton
TypeID: 67
MaxHealth: 5
Prefab: HarvestableSpawner_111mountain herb3
TypeID: 111
MaxHealth: 0
Prefab: Prefab_Resource_18Dust
TypeID: 18
MaxHealth: 5
Prefab: HarvestableSpawner_18Dust
TypeID: 18
MaxHealth: 0
Prefab: Prefab_Resource_1Spruce
TypeID: 1
MaxHealth: 5
Prefab: HarvestableSpawner_73Sweetgrass
TypeID: 73
MaxHealth: 0
Prefab: Prefab_Resource_35RedNymph
TypeID: 35
MaxHealth: 5
Prefab: HarvestableSpawner_72MinigameOre
TypeID: 72
MaxHealth: 0
Prefab: HarvestableSpawner_67Northwind Cotton
TypeID: 67
MaxHealth: 0
Prefab: HarvestableSpawner_57Queen's Lily
TypeID: 57
MaxHealth: 0
Prefab: HarvestableSpawner_103mountain tree1
TypeID: 103
MaxHealth: 0
Prefab: Prefab_Resource_3IronOre
TypeID: 3
MaxHealth: 20
Prefab: HarvestableSpawner_87Generic alchemy
TypeID: 87
MaxHealth: 0
Prefab: Prefab_Resource_31Bloodpetal
TypeID: 31
MaxHealth: 5
Prefab: HarvestableSpawner_1Spruce tree
TypeID: 1
MaxHealth: 0
Prefab: HarvestableSpawner_40Night's Bloom
TypeID: 40
MaxHealth: 0
Prefab: Prefab_Resource_28HorsetailReedBass
TypeID: 28
MaxHealth: 5
Prefab: HarvestableSpawner_11Redberries
TypeID: 11
MaxHealth: 0
Prefab: HarvestableSpawner_20Cavern Puffball
TypeID: 20
MaxHealth: 0
Prefab: HarvestableSpawner_37Ancient's Tears
TypeID: 37
MaxHealth: 0
Prefab: HarvestableSpawner_107mountain Ore2
TypeID: 107
MaxHealth: 0
Prefab: Prefab_Resource_27RockLobster
TypeID: 27
MaxHealth: 5
Prefab: Prefab_Resource_11RedberryBush
TypeID: 11
MaxHealth: 5
Prefab: HarvestableSpawner_62Chili Peppers
TypeID: 62
MaxHealth: 0
Prefab: HarvestableSpawner_106mountain Ore1
TypeID: 106
MaxHealth: 0
Prefab: HarvestableSpawner_56Deepforest Daisy
TypeID: 56
MaxHealth: 0
Prefab: HarvestableSpawner_105mountain tree3
TypeID: 105
MaxHealth: 0
Prefab: HarvestableSpawner_53Drakefire Root
TypeID: 53
MaxHealth: 0
Prefab: HarvestableSpawner_66Pumpkins
TypeID: 66
MaxHealth: 0
Prefab: Prefab_Resource_34SorcerersWeed
TypeID: 34
MaxHealth: 5
Prefab: HarvestableSpawner_112Rye
TypeID: 112
MaxHealth: 0
Prefab: HarvestableSpawner_3Iron ore
TypeID: 3
MaxHealth: 0
Prefab: Prefab_Resource_66Pumpkin_Patch
TypeID: 66
MaxHealth: 5
Prefab: HarvestableSpawner_73MedicinalHerbs
TypeID: 73
MaxHealth: 0
Prefab: HarvestableSpawner_33Silvermirror Iris
TypeID: 33
MaxHealth: 0
Prefab: HarvestableSpawner_69Cabbage
TypeID: 69
MaxHealth: 0
Prefab: HarvestableSpawner_13Arcane Everbloom
TypeID: 13
MaxHealth: 0
Prefab: Prefab_Resource_61Eggplant_Field
TypeID: 61
MaxHealth: 5
Prefab: HarvestableSpawner_48Sorrowleaf
TypeID: 48
MaxHealth: 0
Prefab: Prefab_Resource_63Corn_Field
TypeID: 63
MaxHealth: 5
Prefab: HarvestableSpawner_39Dawnflame Ivy
TypeID: 39
MaxHealth: 0
Prefab: HarvestableSpawner_54Golden Sunflower
TypeID: 54
MaxHealth: 0
Prefab: Prefab_Resource_37AncientsTears
TypeID: 37
MaxHealth: 5
Prefab: HarvestableSpawner_21Charcoal Snapper
TypeID: 21
MaxHealth: 0
Prefab: HarvestableSpawner_82Spider Egg
TypeID: 82
MaxHealth: 0
Prefab: HarvestableSpawner_34Sorcerer's Weed
TypeID: 34
MaxHealth: 0
Prefab: HarvestableSpawner_75Aurora Trout
TypeID: 75
MaxHealth: 0
Prefab: HarvestableSpawner_47Spellspore Cap
TypeID: 47
MaxHealth: 0
Prefab: HarvestableSpawner_109Skyfall Orchid
TypeID: 109
MaxHealth: 0
Prefab: HarvestableSpawner_52Shyflower Orchid
TypeID: 52
MaxHealth: 0
Prefab: HarvestableSpawner_110mountain herb2
TypeID: 110
MaxHealth: 0
Prefab: HarvestableSpawner_38Dandelions
TypeID: 38
MaxHealth: 0
Prefab: HarvestableSpawner_10Barley
TypeID: 10
MaxHealth: 0
Prefab: HarvestableSpawner_51Royal Daisy
TypeID: 51
MaxHealth: 0
Prefab: Prefab_Resource_20CaveShroom
TypeID: 20
MaxHealth: 20
Prefab: HarvestableSpawner_74Sven Herb 2
TypeID: 74
MaxHealth: 0
Prefab: HarvestableSpawner_69Potatoes
TypeID: 69
MaxHealth: 0
Prefab: HarvestableSpawner_114Coldwater Lily
TypeID: 114
MaxHealth: 0
Prefab: HarvestableSpawner_36Noblerose
TypeID: 36
MaxHealth: 0
Prefab: Prefab_Resource_10Barley_Field
TypeID: 10
MaxHealth: 5
Prefab: HarvestableSpawner_31Bloodpetal Rose
TypeID: 31
MaxHealth: 0
Prefab: Prefab_Resource_9WildGoopy
TypeID: 9
MaxHealth: 5
Prefab: HarvestableSpawner_83Gravelstem Whiteflower
TypeID: 83
MaxHealth: 0
Prefab: Prefab_Resource_41FallsHydrangea
TypeID: 41
MaxHealth: 5
Prefab: HarvestableSpawner_50Haniflower
TypeID: 50
MaxHealth: 0
======================================================================
End of resource data

View File

@@ -1,14 +0,0 @@
Cursebreaker Resources - 10_3.unity Scene
======================================================================
Total resources found: 1
----------------------------------------------------------------------
Resource: HarvestableSpawner_38Dandelions
TypeID: 38
MaxHealth: 0
Position: (1746.709717, 44.599632, 299.696503)
======================================================================
End of resource data

View File

@@ -1,19 +0,0 @@
Cursebreaker Resources - 10_3.unity Scene
======================================================================
Total resources found: 2
----------------------------------------------------------------------
Resource: HarvestableSpawner_11Redberries
TypeID: 11
MaxHealth: 0
Position: (1769.135864, 32.664658, 150.395081)
Resource: HarvestableSpawner_38Dandelions
TypeID: 38
MaxHealth: 0
Position: (1746.709717, 44.599632, 299.696503)
======================================================================
End of resource data

View File

@@ -161,6 +161,8 @@ pub fn build_world_from_documents(
// PASS 3: Execute all deferred linking callbacks // PASS 3: Execute all deferred linking callbacks
let entity_map = linking_ctx.into_inner().execute_callbacks(&mut world); let entity_map = linking_ctx.into_inner().execute_callbacks(&mut world);
info!("DEBUG (build_world_from_documents): Final scene entity_map size: {}", entity_map.len());
Ok((world, entity_map)) Ok((world, entity_map))
} }
@@ -312,9 +314,14 @@ pub fn build_world_from_documents_into(
// PASS 3: Execute all deferred linking callbacks // PASS 3: Execute all deferred linking callbacks
let final_entity_map = linking_ctx.into_inner().execute_callbacks(world); let final_entity_map = linking_ctx.into_inner().execute_callbacks(world);
info!("DEBUG (build_world_from_documents_into): Spawned {} entities", spawned_entities.len());
info!("DEBUG (build_world_from_documents_into): final_entity_map size: {}, entity_map size before extend: {}", final_entity_map.len(), entity_map.len());
// Update caller's entity_map with new mappings // Update caller's entity_map with new mappings
entity_map.extend(final_entity_map); entity_map.extend(final_entity_map);
info!("DEBUG (build_world_from_documents_into): entity_map size after extend: {}", entity_map.len());
Ok(spawned_entities) Ok(spawned_entities)
} }
@@ -359,14 +366,30 @@ fn attach_component(
let go_ref = yaml_helpers::get_file_ref(yaml, "m_GameObject"); let go_ref = yaml_helpers::get_file_ref(yaml, "m_GameObject");
let entity = match go_ref { let entity = match go_ref {
Some(r) => linking_ctx Some(r) => {
let entity_opt = linking_ctx
.borrow() .borrow()
.entity_map() .entity_map()
.get(&r.file_id) .get(&r.file_id)
.copied() .copied();
.ok_or_else(|| {
Error::reference_error(format!("Unknown GameObject: {}", r.file_id)) match entity_opt {
})?, Some(e) => {
// Debug logging for Interactable_Resource MonoBehaviours
if doc.class_name == "MonoBehaviour" {
if let Some(script_ref) = yaml_helpers::get_external_ref(yaml, "m_Script") {
if script_ref.guid.as_str() == "d39ddbf1c2c3d1a4baa070e5e76548bd" {
info!("DEBUG: Found GameObject entity {:?} for Interactable_Resource MonoBehaviour (FileID: {})", e, doc.file_id);
}
}
}
e
}
None => {
return Err(Error::reference_error(format!("Unknown GameObject: {}", r.file_id)));
}
}
}
None => { None => {
// Some components might not have m_GameObject (e.g., standalone assets) // Some components might not have m_GameObject (e.g., standalone assets)
warn!( warn!(
@@ -424,6 +447,11 @@ fn attach_component(
if let Some(script_ref) = yaml_helpers::get_external_ref(yaml, "m_Script") { if let Some(script_ref) = yaml_helpers::get_external_ref(yaml, "m_Script") {
// Resolve GUID to class name // Resolve GUID to class name
if let Some(class_name) = resolver.resolve_class_name(script_ref.guid.as_str()) { if let Some(class_name) = resolver.resolve_class_name(script_ref.guid.as_str()) {
// Debug logging for specific GUID
if script_ref.guid.as_str() == "d39ddbf1c2c3d1a4baa070e5e76548bd" {
info!("DEBUG: Found Interactable_Resource GUID! Resolved to class name: {}", class_name);
}
// Try to find a registered custom component with this class name // Try to find a registered custom component with this class name
let mut found_custom = false; let mut found_custom = false;
for reg in inventory::iter::<crate::types::ComponentRegistration> { for reg in inventory::iter::<crate::types::ComponentRegistration> {
@@ -433,6 +461,7 @@ fn attach_component(
if (reg.parse_and_insert)(yaml, &ctx, world, entity) { if (reg.parse_and_insert)(yaml, &ctx, world, entity) {
// Successfully parsed and inserted // Successfully parsed and inserted
linking_ctx.borrow_mut().entity_map_mut().insert(doc.file_id, entity); linking_ctx.borrow_mut().entity_map_mut().insert(doc.file_id, entity);
info!("DEBUG: Successfully inserted component: {}", class_name);
} }
break; break;
} }

View File

@@ -136,12 +136,12 @@ impl UnityPrefab {
/// ///
/// # Example /// # Example
/// ```ignore /// ```ignore
/// let mut instance = prefab.instantiate(); /// let mut instance = prefab.instantiate(None);
/// instance.override_value(file_id, "m_Name", "Player1".into())?; /// instance.override_value(file_id, "m_Name", "Player1".into())?;
/// let entities = instance.spawn_into(&mut world, &mut entity_map)?; /// let entities = instance.spawn_into(&mut world, &mut entity_map)?;
/// ``` /// ```
pub fn instantiate(&self) -> crate::types::PrefabInstance { pub fn instantiate(&self, file_id_counter: Option<std::sync::Arc<std::cell::Cell<i64>>>) -> crate::types::PrefabInstance {
crate::types::PrefabInstance::new(self) crate::types::PrefabInstance::new(self, file_id_counter)
} }
} }

View File

@@ -8,6 +8,7 @@ use sparsey::{Entity, World};
use std::collections::HashMap; use std::collections::HashMap;
use std::path::PathBuf; use std::path::PathBuf;
use std::sync::Arc; use std::sync::Arc;
use std::cell::Cell;
/// An instance of a Unity prefab ready for spawning into a scene /// An instance of a Unity prefab ready for spawning into a scene
/// ///
@@ -20,7 +21,7 @@ use std::sync::Arc;
/// # Example /// # Example
/// ```ignore /// ```ignore
/// let prefab = /* load UnityPrefab */; /// let prefab = /* load UnityPrefab */;
/// let mut instance = prefab.instantiate(); /// let mut instance = prefab.instantiate(None);
/// instance.override_value(file_id, "m_Name", "Player1".into())?; /// instance.override_value(file_id, "m_Name", "Player1".into())?;
/// instance.override_value(file_id, "m_LocalPosition.x", 100.0.into())?; /// instance.override_value(file_id, "m_LocalPosition.x", 100.0.into())?;
/// let entities = instance.spawn_into(&mut world, &mut entity_map)?; /// let entities = instance.spawn_into(&mut world, &mut entity_map)?;
@@ -40,7 +41,8 @@ pub struct PrefabInstance {
/// Sequential counter for generating new FileIDs /// Sequential counter for generating new FileIDs
/// Starts at i64::MAX and decrements to avoid collisions with scene FileIDs /// Starts at i64::MAX and decrements to avoid collisions with scene FileIDs
next_file_id: i64, /// NOTE: This should be shared across all instances via a reference
next_file_id: Arc<std::cell::Cell<i64>>,
/// Source prefab path for debugging /// Source prefab path for debugging
source_path: PathBuf, source_path: PathBuf,
@@ -50,15 +52,22 @@ impl PrefabInstance {
/// Create a new instance from a Unity prefab /// Create a new instance from a Unity prefab
/// ///
/// This clones all documents from the prefab and initializes FileID remapping. /// This clones all documents from the prefab and initializes FileID remapping.
pub fn new(prefab: &UnityPrefab) -> Self { ///
/// # Arguments
/// * `prefab` - The prefab to instantiate
/// * `file_id_counter` - Optional shared FileID counter to ensure uniqueness across instances
pub fn new(prefab: &UnityPrefab, file_id_counter: Option<Arc<Cell<i64>>>) -> Self {
// Clone all documents from the prefab // Clone all documents from the prefab
let documents = prefab.documents.clone(); let documents = prefab.documents.clone();
// Use provided counter or create a new one starting at i64::MAX
let next_file_id = file_id_counter.unwrap_or_else(|| Arc::new(Cell::new(i64::MAX)));
let mut instance = Self { let mut instance = Self {
documents, documents,
file_id_map: HashMap::new(), file_id_map: HashMap::new(),
overrides: HashMap::new(), overrides: HashMap::new(),
next_file_id: i64::MAX, next_file_id,
source_path: prefab.path.clone(), source_path: prefab.path.clone(),
}; };
@@ -73,9 +82,9 @@ impl PrefabInstance {
/// ///
/// Uses a sequential counter starting from i64::MAX and decrementing. /// Uses a sequential counter starting from i64::MAX and decrementing.
/// This avoids collisions with typical scene FileIDs which are positive. /// This avoids collisions with typical scene FileIDs which are positive.
fn generate_file_id(&mut self) -> FileID { fn generate_file_id(&self) -> FileID {
let id = self.next_file_id; let id = self.next_file_id.get();
self.next_file_id -= 1; self.next_file_id.set(id - 1);
FileID::from_i64(id) FileID::from_i64(id)
} }
@@ -449,6 +458,9 @@ pub struct PrefabResolver<'a> {
/// Prefab GUID resolver for nested prefabs /// Prefab GUID resolver for nested prefabs
prefab_guid_resolver: Option<&'a crate::parser::PrefabGuidResolver>, prefab_guid_resolver: Option<&'a crate::parser::PrefabGuidResolver>,
/// Shared FileID counter to ensure uniqueness across all prefab instances
file_id_counter: Arc<Cell<i64>>,
} }
impl<'a> PrefabResolver<'a> { impl<'a> PrefabResolver<'a> {
@@ -463,6 +475,7 @@ impl<'a> PrefabResolver<'a> {
instantiation_stack: Vec::new(), instantiation_stack: Vec::new(),
guid_resolver: None, guid_resolver: None,
prefab_guid_resolver: None, prefab_guid_resolver: None,
file_id_counter: Arc::new(Cell::new(i64::MAX)),
} }
} }
@@ -490,6 +503,7 @@ impl<'a> PrefabResolver<'a> {
instantiation_stack: Vec::new(), instantiation_stack: Vec::new(),
guid_resolver, guid_resolver,
prefab_guid_resolver: Some(prefab_guid_resolver), prefab_guid_resolver: Some(prefab_guid_resolver),
file_id_counter: Arc::new(Cell::new(i64::MAX)),
} }
} }
@@ -524,8 +538,8 @@ impl<'a> PrefabResolver<'a> {
// 2. Load prefab via load_prefab() // 2. Load prefab via load_prefab()
let prefab = self.load_prefab(guid)?; let prefab = self.load_prefab(guid)?;
// 3. Create PrefabInstance // 3. Create PrefabInstance with shared FileID counter
let mut instance = prefab.instantiate(); let mut instance = prefab.instantiate(Some(self.file_id_counter.clone()));
// 4. Apply component.modifications using override_value() // 4. Apply component.modifications using override_value()
for modification in &component.modifications { for modification in &component.modifications {
@@ -605,8 +619,8 @@ impl<'a> PrefabResolver<'a> {
// Push to stack // Push to stack
self.instantiation_stack.push(prefab_id.clone()); self.instantiation_stack.push(prefab_id.clone());
// Create instance // Create instance with shared FileID counter
let instance = prefab.instantiate(); let instance = prefab.instantiate(Some(self.file_id_counter.clone()));
// Find nested prefab references // Find nested prefab references
let nested_prefabs = self.find_nested_prefabs(&instance)?; let nested_prefabs = self.find_nested_prefabs(&instance)?;
@@ -617,8 +631,8 @@ impl<'a> PrefabResolver<'a> {
for (_parent_file_id, nested_component) in nested_prefabs { for (_parent_file_id, nested_component) in nested_prefabs {
// Load the referenced prefab // Load the referenced prefab
if let Ok(nested_prefab) = self.load_prefab(&nested_component.prefab_ref.guid) { if let Ok(nested_prefab) = self.load_prefab(&nested_component.prefab_ref.guid) {
// Apply modifications // Apply modifications with shared FileID counter
let mut nested_instance = nested_prefab.instantiate(); let mut nested_instance = nested_prefab.instantiate(Some(self.file_id_counter.clone()));
for modification in &nested_component.modifications { for modification in &nested_component.modifications {
nested_instance.override_value( nested_instance.override_value(
modification.target_file_id, modification.target_file_id,