prefab spawning bugfix
This commit is contained in:
@@ -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
|
||||
@@ -161,6 +161,8 @@ pub fn build_world_from_documents(
|
||||
// PASS 3: Execute all deferred linking callbacks
|
||||
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))
|
||||
}
|
||||
|
||||
@@ -312,9 +314,14 @@ pub fn build_world_from_documents_into(
|
||||
// PASS 3: Execute all deferred linking callbacks
|
||||
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
|
||||
entity_map.extend(final_entity_map);
|
||||
|
||||
info!("DEBUG (build_world_from_documents_into): entity_map size after extend: {}", entity_map.len());
|
||||
|
||||
Ok(spawned_entities)
|
||||
}
|
||||
|
||||
@@ -359,14 +366,30 @@ fn attach_component(
|
||||
let go_ref = yaml_helpers::get_file_ref(yaml, "m_GameObject");
|
||||
|
||||
let entity = match go_ref {
|
||||
Some(r) => linking_ctx
|
||||
.borrow()
|
||||
.entity_map()
|
||||
.get(&r.file_id)
|
||||
.copied()
|
||||
.ok_or_else(|| {
|
||||
Error::reference_error(format!("Unknown GameObject: {}", r.file_id))
|
||||
})?,
|
||||
Some(r) => {
|
||||
let entity_opt = linking_ctx
|
||||
.borrow()
|
||||
.entity_map()
|
||||
.get(&r.file_id)
|
||||
.copied();
|
||||
|
||||
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 => {
|
||||
// Some components might not have m_GameObject (e.g., standalone assets)
|
||||
warn!(
|
||||
@@ -424,6 +447,11 @@ fn attach_component(
|
||||
if let Some(script_ref) = yaml_helpers::get_external_ref(yaml, "m_Script") {
|
||||
// Resolve GUID to class name
|
||||
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
|
||||
let mut found_custom = false;
|
||||
for reg in inventory::iter::<crate::types::ComponentRegistration> {
|
||||
@@ -433,6 +461,7 @@ fn attach_component(
|
||||
if (reg.parse_and_insert)(yaml, &ctx, world, entity) {
|
||||
// Successfully parsed and inserted
|
||||
linking_ctx.borrow_mut().entity_map_mut().insert(doc.file_id, entity);
|
||||
info!("DEBUG: Successfully inserted component: {}", class_name);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -136,12 +136,12 @@ impl UnityPrefab {
|
||||
///
|
||||
/// # Example
|
||||
/// ```ignore
|
||||
/// let mut instance = prefab.instantiate();
|
||||
/// let mut instance = prefab.instantiate(None);
|
||||
/// instance.override_value(file_id, "m_Name", "Player1".into())?;
|
||||
/// let entities = instance.spawn_into(&mut world, &mut entity_map)?;
|
||||
/// ```
|
||||
pub fn instantiate(&self) -> crate::types::PrefabInstance {
|
||||
crate::types::PrefabInstance::new(self)
|
||||
pub fn instantiate(&self, file_id_counter: Option<std::sync::Arc<std::cell::Cell<i64>>>) -> crate::types::PrefabInstance {
|
||||
crate::types::PrefabInstance::new(self, file_id_counter)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ use sparsey::{Entity, World};
|
||||
use std::collections::HashMap;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
use std::cell::Cell;
|
||||
|
||||
/// An instance of a Unity prefab ready for spawning into a scene
|
||||
///
|
||||
@@ -20,7 +21,7 @@ use std::sync::Arc;
|
||||
/// # Example
|
||||
/// ```ignore
|
||||
/// 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_LocalPosition.x", 100.0.into())?;
|
||||
/// let entities = instance.spawn_into(&mut world, &mut entity_map)?;
|
||||
@@ -40,7 +41,8 @@ pub struct PrefabInstance {
|
||||
|
||||
/// Sequential counter for generating new 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_path: PathBuf,
|
||||
@@ -50,15 +52,22 @@ impl PrefabInstance {
|
||||
/// Create a new instance from a Unity prefab
|
||||
///
|
||||
/// 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
|
||||
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 {
|
||||
documents,
|
||||
file_id_map: HashMap::new(),
|
||||
overrides: HashMap::new(),
|
||||
next_file_id: i64::MAX,
|
||||
next_file_id,
|
||||
source_path: prefab.path.clone(),
|
||||
};
|
||||
|
||||
@@ -73,9 +82,9 @@ impl PrefabInstance {
|
||||
///
|
||||
/// Uses a sequential counter starting from i64::MAX and decrementing.
|
||||
/// This avoids collisions with typical scene FileIDs which are positive.
|
||||
fn generate_file_id(&mut self) -> FileID {
|
||||
let id = self.next_file_id;
|
||||
self.next_file_id -= 1;
|
||||
fn generate_file_id(&self) -> FileID {
|
||||
let id = self.next_file_id.get();
|
||||
self.next_file_id.set(id - 1);
|
||||
FileID::from_i64(id)
|
||||
}
|
||||
|
||||
@@ -449,6 +458,9 @@ pub struct PrefabResolver<'a> {
|
||||
|
||||
/// Prefab GUID resolver for nested prefabs
|
||||
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> {
|
||||
@@ -463,6 +475,7 @@ impl<'a> PrefabResolver<'a> {
|
||||
instantiation_stack: Vec::new(),
|
||||
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(),
|
||||
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()
|
||||
let prefab = self.load_prefab(guid)?;
|
||||
|
||||
// 3. Create PrefabInstance
|
||||
let mut instance = prefab.instantiate();
|
||||
// 3. Create PrefabInstance with shared FileID counter
|
||||
let mut instance = prefab.instantiate(Some(self.file_id_counter.clone()));
|
||||
|
||||
// 4. Apply component.modifications using override_value()
|
||||
for modification in &component.modifications {
|
||||
@@ -605,8 +619,8 @@ impl<'a> PrefabResolver<'a> {
|
||||
// Push to stack
|
||||
self.instantiation_stack.push(prefab_id.clone());
|
||||
|
||||
// Create instance
|
||||
let instance = prefab.instantiate();
|
||||
// Create instance with shared FileID counter
|
||||
let instance = prefab.instantiate(Some(self.file_id_counter.clone()));
|
||||
|
||||
// Find nested prefab references
|
||||
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 {
|
||||
// Load the referenced prefab
|
||||
if let Ok(nested_prefab) = self.load_prefab(&nested_component.prefab_ref.guid) {
|
||||
// Apply modifications
|
||||
let mut nested_instance = nested_prefab.instantiate();
|
||||
// Apply modifications with shared FileID counter
|
||||
let mut nested_instance = nested_prefab.instantiate(Some(self.file_id_counter.clone()));
|
||||
for modification in &nested_component.modifications {
|
||||
nested_instance.override_value(
|
||||
modification.target_file_id,
|
||||
|
||||
Reference in New Issue
Block a user