- Home /
Cannot modify Prefab
Through an editor script I am loading in a shape file, then trying to modify the position, rotation, and material of a lot of shapes it contains. Using the unity debugger synchronized with monodevelop, I verified that the prefab transforms are modified correctly by the editor script. Up to that point, I have not instantiated any of those prefabs into my scene. In the same script, I save an asset bundle with these objects. When I load the asset bundle back into my scene, the changes to the prefabs are not present. So the objects come in the wrong location, wrong color. After the script has stopped, I look in the project tab and all of the prefab transforms are not modified.
First Question: why are the changes not being saved in the project prefabs?
Other question: When I build the UnityEngine.Object[] array for the BuildPipeline.BuildAssetBundle function, how recursive do I need to be? Let's say for example that I have some GameObject "myobj". Do I need to include the object's transform, collider, renderer, in the array for buildAssetBundle? Or will the function recursively find all dependencies and include them in the asset bundle? I have the impression that if I don't include the child components in the array, then the asset bundle does not include them, and when it's loaded it just creates default components. I want it to include the modified components.
So far the only workaround I can think of is to instantiate my shapes from the shape file, make my modifications to the scene instances, and then build a prefab from the scene instances. This seems tedious though, and I'm sure will consume tons of RAM while the editor script runs, meaning my script might crash sooner rather than later. It also seems silly to me that I start with a prefab, need a prefab for the asset bundle, but cannot use/modify the initial prefab.
I would really be interested in seeing the script you used to import the shapefile. $$anonymous$$y company would love to do that
Answer by kevork · Sep 21, 2011 at 07:26 PM
The changes are likely not being saved because you aren't calling EditorUtility.SetDirty on the asset you want to save.
If you want everything saved in the AssetBundle, use the CollectDependencies and CompleteAssets BuildAssetBundleOptions. There is an example here.
I reviewed that example long before I made my post. It's no help for me, I'm not building asset bundles from a selection in my hierarchy. I have hundreds (and potentially thousands) of asset bundles to make. If I made every asset bundle manually like that, it would take at least a few weeks to build everything. I need to build the asset bundles from assets that are loaded in through my editor script.
I never considered the "SetDirty" function, I will try it and get back to you.
It doesn't matter what input you are building the asset bundles from. Assu$$anonymous$$g you are looping through the assets that you want to make asset bundles out of putting this in your loop
BuildPipeline.BuildAssetBundle(someObject, null, path, BuildAssetBundleOptions.CollectDependencies | BuildAssetBundleOptions.CompleteAssets);
is likely what you want to use.
Thank you that fixed issues with editor script that wouldn't make the changes stick. SetDirty was the missing part of my scripts.
Answer by msknapp · Sep 21, 2011 at 10:36 PM
So I added lines to mark my game objects, and their components, dirty using the EditorUtility.SetDirty function. I also added the "BuildAssetBundleOptions.CompleteAssets" to my arguments that build the asset bundle. Unfortunately what I'm saving into the asset bundle does not match what comes out when I load it into my scene.
assets Before save:
Index, Name, type
0, C4 Terrain, GameObject
1, Building on C4, GameObject
2, Group_1_1, GameObject
3, Mesh1, GameObject
4, Group_2_1, GameObject
5, Mesh2, GameObject
6, Mesh3, GameObject
7, Mesh4, GameObject
* I verified through the debugger that the terrain object transform indeed has the correct position.
assets After loading (order does not matter, changes each time):
Index, Name, type
0, C4, GameObject
1, C4, Transform
2, Mesh1, Mesh
3, Mesh2, Mesh
4, Mesh3, Mesh
5, Mesh4, Mesh
6, C4, TerrainData
7, SplatAlpha 0, Texture2D
* All objects are brought in at the world origin, my changes to the position were lost again.
And yet again, if I look into my project tab, and view the transform attached to my building prefab (not scene instance), the position is at the world origin. My changes to the prefab are not being persisted.
I think that maybe "SetDirty" needs some kind of follow up step? I looked through the EditorUtility but could not find anything. Any ideas?
If you can post your code or some pseudo-code of what you are doing, it will be easier to give you exact answers to your questions.
You can save all the assets in your projects explicitly with AssetDatabase.SaveAssets().
After spending over 40 hours trying to figure this all out I have learned a lot, but still have not solved this problem.
The most important lesson I learned is that the AssetDatabase needs to be updated all the time. What was driving me crazy is that sometimes my terrain or shape objects would just randomly go null. I figured out the culprit was the "AssetDatabase.Refresh" function. I thought this would just make my changes show in the "project" tab. But that is not at all what it does. Any file or folder in the Assets folder that does not have a unique asset path with the AssetDatabase is deleted when the Refresh function is called. Hence I was having random null references to objects that were good before. I realized that I need to use the FileUtil and AssetDatabase class to do all the file/directory moving.
I found the documentation on AssetDatabase here:
http://unity3d.com/support/documentation/$$anonymous$$anual/AssetDatabase.html
but the documentation is not nearly as thorough as it should be. I have a million questions after reading that, and little idea how to correctly use it. What can I expect though, the Unity $$anonymous$$m has never been thorough with their documentation, and it has cost me tons of time.
I also tried using the "StartAssetEditing" and "StopAssetEditing" functions, but those don't seem to have changed anything.
I just wish that somebody would explain to me all of the assumptions, expectations, etc. associated with all the functions of the Unity classes. Especially the AssetDatabase and FileUtil classes. I really want to know when is it necessary to call specific functions, and in what order they should be called. For example, if I use FileUtil to copy a file into my project, do I need to follow up with the AssetDatabase.ImportAsset? The unity documentation does not say. I could go on with a million more questions, but it would take too much space.
Answer by msknapp · Sep 23, 2011 at 03:33 PM
Ok so here is an extremely simplified version of my pseudo-code that does not work:
String dirPath = "Assets\\Shapes\\"+cellName;
String destFilePath = dirPath+"\\"+cellName+".fbx";
AssetDatabase.GenerateUniqueAssetPath(destFilePath.Replace("\\","/"));
DirectoryInfo destDir = new DirectoryInfo(Directory.GetCurrentDirectory()
+ "\\"+dirPath);
if (! destDir.Exists)
destDir.Create();
FileUtil.CopyFileOrDirectory(fileInfo.ToString(),destFilePath.Replace("\\","/"));
AssetDatabase.Refresh();
String s = dirPath.Replace("\\","/")+"/"+cellName+".fbx";
UnityEngine.Object[] assets = AssetDatabase.LoadAllAssetsAtPath(s);
AssetDatabase.StartAssetEditing();
foreach (UnityEngine.Object asset in assets) {
if (! (asset is GameObject))
continue;
GameObject gameObjectAsset = (GameObject)asset;
// there is code here to modify the position and rotation of the game object asset...
// from the debugger I have confirmed that the changes were made to the object correctly.
EditorUtility.SetDirty(gameObjectAsset);
EditorUtility.SetDirty(gameObjectAsset.transform);
EditorUtility.SetDirty(gameObjectAsset.transform.position);
}
AssetDatabase.StopAssetEditing();
AssetDatabase.SaveAssets();
// I select the asset in my project view, under the shapes folder.
// I look in the inspector at the objects I build,
// and the changes I made to the transform are not there.