// Swap assets, replace prefabs, gather levels of detail, add colliders static void AssembleComplete(List <GameObject> completeModels, List <GameObject> assembledModels) { try { AssetDatabase.StartAssetEditing(); foreach (var model in completeModels) { // IMPORTANT: All assets used by models are gathered inside an adjacent folders with the same name var searchPath = AssetDatabase.GetAssetPath(model); searchPath = searchPath.Substring(0, searchPath.Length - ".prefab".Length); // Swap assets for copies created when combining partial models // NOTE: Modifications will not alter original assets, since copies are now being used var gatherer = new GatherAssets.AssetGatherer(searchPath); gatherer.SwapAssets(model); // Configure the complete model AutoLOD.ApplyTo(model); AutoStatic.ApplyTo(model); AutoColliders.ApplyTo(model); //Debug.Log($"Configured prefab: {prefabPath}"); } } finally { AssetDatabase.StopAssetEditing(); AssetDatabase.Refresh(ImportAssetOptions.ForceSynchronousImport); } // IMPORTANT: ReplacePrefabs needs to create placeholders, which cannot occur during AssetDatabase editing foreach (var model in completeModels) { // IMPORTANT: Assembled models will contain only prefabs inside an adjacent folder with the same name // NOTE: Constituent models may contain other constituent models, so search should begin adjacent var prefabPath = AssetDatabase.GetAssetPath(model); prefabPath = prefabPath.Substring(0, prefabPath.Length - ".prefab".Length); var isAssembledModel = !prefabPath.Substring(importPath.Length).Contains("/"); if (!isAssembledModel) { prefabPath = prefabPath.Substring(0, prefabPath.LastIndexOf('/')); } ReplacePrefabs.ApplyTo(model, prefabPath); // Only create scenes from prefabs in RePort if (isAssembledModel) { assembledModels.Add(model); } } }
// Combines partial models (meshes and levels of detail and prefab places) into complete models static void CombinePartial(Dictionary <string, List <GameObject> > partialModels, List <GameObject> completeModels) { // Find or make a merged prefab for each folder in the path // IMPORTANT: This must be done BEFORE ReplacePrefabs.ApplyTo() // so that prefabs can be linked immediately and updated subsequently. // NOTE: Existing merged prefabs will be updated by new imports var mergedPrefabs = new Dictionary <string, GameObject>(); foreach (var path in partialModels.Keys) { // IMPORTANT: this will not create an importPath named RePort, // since importPath ends with '/' which is not included in path. if (!path.StartsWith(importPath)) { continue; } CreateMerged(path, mergedPrefabs); } AssetDatabase.Refresh(ImportAssetOptions.ForceSynchronousImport); try { AssetDatabase.StartAssetEditing(); // Merge prefab consistuents and copy assets // NOTE: If new constituents are added or updated they will be merged into existing model. // NOTE: If additional prefabs are added they will replace placeholders // in the merged model, which will persist through the merge and configure process. foreach (var item in mergedPrefabs) { if (partialModels.ContainsKey(item.Key)) { MergeModels.ApplyTo(item.Value, partialModels[item.Key].ToArray()); } // Assets will be gathered in folder adjacent to merged model // IMPORTANT: Constituent prefabs will maintain independent asset copies. var gatherer = new GatherAssets.AssetGatherer(item.Key); gatherer.CopyAssets(item.Value); completeModels.Add(item.Value); //Debug.Log($"Gathered assets from {item.Value.name} to {item.Key}"); } } finally { AssetDatabase.StopAssetEditing(); AssetDatabase.Refresh(ImportAssetOptions.ForceSynchronousImport); } }