Js script randomly crashes Unity

Hi, let me present you the situation:

I need to import in .fbx format some geometry I have generated. As we know, we can’t use object with more than 65536 vertices. So, I split my original object into smaller ones, and I want to make a prefab with all of them.
And has it can be quite important: I’m a total newbie with Unity and with it’s scripting system, so I might be making enormous mistakes.

Substantially, my script works like this:

  • search for newly imported objects which match my conditions
  • make a treatment on them (position, rotation, parenting)
  • create a prefab with all of this.

I’m actually getting random crashes on this script, despite the fact that I have written it again and again, trying to make it as efficient as possible.

Here is a overview of my js script :

class MyClass extends AssetPostprocessor
{
     private static var myHasTable: Hashtable = new Hashtable();

     private function OnPostprocessModel(imported_game_object : GameObject)
     {
         if(<the asset fits some conditions I check on it's assetpath>)
         {	
		// Prevent the script from stopping if there is an error with an object
		try
		{	
			var prefab_part : GameObject = GameObject.Instantiate(AssetDatabase.LoadMainAssetAtPath(assetPath)) as GameObject;
			myHasTable.Add(Path.GetFileNameWithoutExtension(assetPath), prefab_part);
		}
		catch(error)
		{
				
		}
	}
    }

private static function OnPostprocessAllAssets(importedAssets : String[], deletedAssets : String[], movedAssets : String[], movedFromAssetPaths : String[]) 
	{	
		if(myHasTable.Count > 0)
		{	
			var tempPrefab : GameObject = new GameObject(); 
			var multiFilePrefab : Object = new Object();
			
			for(var key in myHasTable.Keys)
			{	
				var myTextReader : XmlTextReader = new XmlTextReader(Path.Combine("Assets", "multi_export_global_file.xml"));
				myTextReader.Read();
								
				while(1)
				{
					if(myTextReader.GetAttribute("name") == key)
					{	
						myHasTable[key].transform.parent = tempPrefab.transform;
						myHasTable[key].transform.position = Vector3(parseFloat(megf_reader.GetAttribute("xposition")), 0.0f, parseFloat(megf_reader.GetAttribute("zposition")));
						myHasTable[key].transform.Rotate(0.0f, 0.0f, 180.0f);
						break;
					}
					
					if(!myTextReader.Read())
					{
						break;
					}
				}
				
				myTextReader.Close();
			}
		
			multiFilePrefab = EditorUtility.CreateEmptyPrefab(Path.Combine("Assets", "multi_file_prefab.prefab"));
			EditorUtility.ReplacePrefab(tempPrefab, multiFilePrefab, ReplacePrefabOptions.ReplaceNameBased);															
			GameObject.DestroyImmediate(tempPrefab);
			
		}
		
		myHasTable.Clear();
	}

}

Sorry if the code is not very clear, quite hard to make it clean on a forum interface.

To launch the script, I select the concerned assets in the project view and then right click → Reimport.

Sometimes if works perfectly, and I get my prefab created with all object at the right place.
Sometimes it’s quite a mess, the prefab is missing but I have all my object on a gameobject (so the one called “tempPrefab” in the script)
Sometimes object’s are missing on the prefab.
And quite often Unity simply crashes, with no error warning.
I can even have (just happened right now) the two opposite behavior with the same assets: worked perfectly the first time I launched the script, crashed the second one.

If I’m note clear enough, let me know it, I’ll try to make it easier to understand, or post a attached version of the script if needed.

Last thing I’ve just thought about: does the 65536 vertices limitation concerns the prefab too? I haven’t found nothing about it, hop it’s only about imported object themselves.

I would limit that while(1) to while(i<20). just keep track of a new variable to limit it. Just be logical about it

yes, the 65k vertices limitation applies to every mesh in Unity. Prefab or not. (Every Mesh, not every group of meshes, so you can group a bunch of them together.)

Is it a crash? or a hang/freeze? ushually when its a hang/freeze that means your in a infinite loop. But it can also flat out crash if in a infinite loop which is allocating memory and memory runs out, when this happens there sometimes is and sometimes isnt a message saying out of memory.

Another thing you should do is take a look at AssetDatabase.StartAssetEditing and AssetDatabase.StopAssetEditing.

BigMisterB: Ok, now I understand why I had these kind of problems. I thought prefab was just containers, not considered as object themselves.

Bdev: it’s actually a crash, I mean, with the bug report window. Not juste a freeze. Thank you for AssetDatabase propertys, I’m gonna look at this.

Edit:
I have just figured out that OnPostprocessAllAssets is called twice when I re-import an asset folder, preventing me from doing what I want.
Anny idea about this double call?

Hi, I have progressed with all of this.

Instead of using OnPostprocessAllAssets() I’m only using OnPostprocessModel(). All my datas are now static, and I am finally able to almost do what I want to.

So here is the way I work now:

  • Loading assets one by one. If the conditions I check are valid, If there are enough remaining vertices in the current prefab, I had it to the prefab. If the remaining vertices are insufficient, I “close” the prefab, create a new one, add my object to the new one.
    No problems here, works nicely.

  • When it’s done, I want to instantiate all prefabs, and group them in the same GameObject (EditorUtility.InstantiatePrefab(my_prefab)).
    The instantiation part works fine, prefabs are now in my scene’s hierarchy.

  • Then I browse all my prefabs this way : var temp_prefab : GameObject = GameObject.Find(prefab_name)
    and put them in a object using : temp_prefab.transform.parent = my_main_object.transform.
    It works for some of them, fails for the others. Find() returns me null for some of the objects, always the same. But the instantiated prefab are actually here, I can drag them manually in my main object, works normally.

Any idea with the source of this problem?
I’ve tried with different data sets, similar behavior.
I’ve tried to store the result of InstantiatePrefab() in a temp variable instead of using Find(), same behavior.
The script keeps returning me null for some hierarchy objects that exist.
Can it bee about asynchronous execution of scripts?

EDIT:

  • It seems to always fail with prefabs created at last.
  • And I can access them trough another script I run after the first one. Make me think more and more to a timing problem.

RESOLVED:
I didn’t manage to resolve the problem with the last instantiated prefabs that were null, but I have just figured out that it is possible to create a prefab from a object that is the parent of all my sub objects.

Here is how it works:

  • Create a master object
  • Load all sub objects and make them child of the master one: sub_object.transform.parent = master.transform
  • Create an empty prefab: var my_new_prefab : Object = EditorUtility.CreateEmptyPrefab(“my/prefab/path”)
  • Replace the prefab content : EditorUtility.ReplacePrefab(my_master_object, my_new_prefab, ReplacePrefabOptions.ReplaceNameBased);
  • Instantiate the obtained prefab : EditorUtility.InstantiatePrefab(new_prefab);

And that’s all. Quite happy to make it finally work.