Skip to content

Commit b9355a0

Browse files
authored
Merge pull request #314 from Unity-Technologies/UNI-23144-convert-to-prefab-dont-override-fbx
Uni 23144 convert to prefab dont override fbx
2 parents 2d18ef0 + d32b6a1 commit b9355a0

File tree

3 files changed

+96
-4
lines changed

3 files changed

+96
-4
lines changed

Assets/FbxExporters/Editor/ConvertToModel.cs

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,29 @@ public static GameObject Convert (
117117
string directoryFullPath = null,
118118
string fbxFullPath = null)
119119
{
120+
// Only create the prefab (no FBX export) if we have selected the root of a model prefab instance.
121+
// Children of model prefab instances will also have "model prefab instance"
122+
// as their prefab type, so it is important that it is the root that is selected.
123+
//
124+
// e.g. If I have the following hierarchy:
125+
// Cube
126+
// -- Sphere
127+
//
128+
// Both the Cube and Sphere will have ModelPrefabInstance as their prefab type.
129+
// However, when selecting the Sphere to convert, we don't want to connect it to the
130+
// existing FBX but create a new FBX containing just the sphere.
131+
PrefabType unityPrefabType = PrefabUtility.GetPrefabType(toConvert);
132+
if (unityPrefabType == PrefabType.ModelPrefabInstance && toConvert.Equals(PrefabUtility.FindPrefabRoot(toConvert))) {
133+
// don't re-export fbx
134+
// create prefab out of model instance in scene, link to existing fbx
135+
var mainAsset = PrefabUtility.GetPrefabParent(toConvert) as GameObject;
136+
var mainAssetRelPath = AssetDatabase.GetAssetPath(mainAsset);
137+
var mainAssetAbsPath = Directory.GetParent(Application.dataPath) + "/" + mainAssetRelPath;
138+
SetupFbxPrefab(toConvert, mainAsset, mainAssetRelPath, mainAssetAbsPath);
139+
140+
return toConvert;
141+
}
142+
120143
if (string.IsNullOrEmpty(fbxFullPath)) {
121144
// Generate a unique filename.
122145
if (string.IsNullOrEmpty (directoryFullPath)) {
@@ -155,12 +178,27 @@ public static GameObject Convert (
155178
// relative to the project, not relative to the assets folder.
156179
var unityMainAsset = AssetDatabase.LoadMainAssetAtPath (projectRelativePath) as GameObject;
157180
if (!unityMainAsset) {
158-
throw new System.Exception ("Failed to convert " + toConvert.name);;
181+
throw new System.Exception ("Failed to convert " + toConvert.name);
159182
}
160183

161184
// Copy the mesh/materials from the FBX
162185
UpdateFromSourceRecursive (toConvert, unityMainAsset);
163186

187+
SetupFbxPrefab (toConvert, unityMainAsset, projectRelativePath, fbxFullPath);
188+
189+
toConvert.name = Path.GetFileNameWithoutExtension (fbxFullPath);
190+
return toConvert;
191+
}
192+
193+
194+
/// <summary>
195+
/// Create the prefab and connect it to the given fbx asset.
196+
/// </summary>
197+
/// <param name="toConvert">Hierarchy to convert.</param>
198+
/// <param name="unityMainAsset">Main asset in the FBX.</param>
199+
/// <param name="projectRelativePath">Fbx project relative path.</param>
200+
/// <param name="fbxFullPath">Fbx full path.</param>
201+
public static void SetupFbxPrefab(GameObject toConvert, GameObject unityMainAsset, string projectRelativePath, string fbxFullPath){
164202
// Set up the FbxPrefab component so it will auto-update.
165203
// Make sure to delete whatever FbxPrefab history we had.
166204
var fbxPrefab = toConvert.GetComponent<FbxPrefab>();
@@ -179,9 +217,6 @@ public static GameObject Convert (
179217
string.Format("Failed to create prefab asset in [{0}] from fbx [{1}]",
180218
prefabFileName, fbxFullPath));
181219
}
182-
183-
toConvert.name = Path.GetFileNameWithoutExtension (fbxFullPath);
184-
return toConvert;
185220
}
186221

187222
/// <summary>

Assets/FbxExporters/Editor/UnitTests/ConvertToModelTest.cs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,5 +256,59 @@ public void TestInstanceNameMatchesFilename()
256256

257257
Assert.AreEqual (Path.GetFileNameWithoutExtension (path), cube.name);
258258
}
259+
260+
[Test]
261+
public void TestConvertModelInstance()
262+
{
263+
// expected result: prefab is linked to originally exported
264+
// fbx and no new fbx is created.
265+
266+
// create hierarchy (Cube->Sphere)
267+
var cube = GameObject.CreatePrimitive (PrimitiveType.Cube);
268+
var sphere = GameObject.CreatePrimitive (PrimitiveType.Sphere);
269+
270+
sphere.transform.SetParent (cube.transform);
271+
272+
// export using regular model export
273+
var filename = GetRandomFileNamePath();
274+
GameObject fbxObj = ExportSelection (filename, cube);
275+
276+
// add back to scene
277+
GameObject fbxInstance = PrefabUtility.InstantiatePrefab (fbxObj) as GameObject;
278+
Assert.That (fbxInstance, Is.Not.Null);
279+
280+
// attach some components
281+
var rigidBody = fbxInstance.AddComponent<Rigidbody> ();
282+
Assert.That (rigidBody, Is.Not.Null);
283+
284+
var instanceSphere = fbxInstance.transform.GetChild (0);
285+
Assert.That (instanceSphere, Is.Not.Null);
286+
287+
var boxCollider = instanceSphere.gameObject.AddComponent<BoxCollider> ();
288+
Assert.That (boxCollider, Is.Not.Null);
289+
290+
// convert to prefab
291+
GameObject converted = ConvertToModel.Convert (fbxInstance, Path.GetDirectoryName(filename));
292+
Assert.That (converted, Is.EqualTo (fbxInstance));
293+
294+
// check meshes link to original fbx
295+
var prefabCubeMesh = fbxInstance.GetComponent<MeshFilter>().sharedMesh;
296+
Assert.That (prefabCubeMesh, Is.Not.Null);
297+
298+
var fbxObjAssetPath = AssetDatabase.GetAssetPath (fbxObj);
299+
300+
Assert.That (AssetDatabase.GetAssetPath (prefabCubeMesh), Is.EqualTo (fbxObjAssetPath));
301+
302+
var prefabSphere = fbxInstance.transform.GetChild (0);
303+
Assert.That (prefabSphere, Is.Not.Null);
304+
var prefabSphereMesh = prefabSphere.GetComponent<MeshFilter> ().sharedMesh;
305+
Assert.That (prefabSphere, Is.Not.Null);
306+
307+
Assert.That (AssetDatabase.GetAssetPath (prefabSphereMesh), Is.EqualTo (fbxObjAssetPath));
308+
309+
// check that components are still there
310+
Assert.That (fbxInstance.GetComponent<Rigidbody>(), Is.Not.Null);
311+
Assert.That (prefabSphere.GetComponent<BoxCollider> (), Is.Not.Null);
312+
}
259313
}
260314
}

Assets/FbxExporters/Editor/UnitTests/ExporterTestBase.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,10 @@ protected virtual GameObject ExportSelection(params Object[] selected)
223223
{
224224
// export selected to a file, then return the root
225225
var filename = GetRandomFileNamePath();
226+
return ExportSelection (filename, selected);
227+
}
226228

229+
protected virtual GameObject ExportSelection(string filename, params Object[] selected){
227230
Debug.unityLogger.logEnabled = false;
228231
var fbxFileName = FbxExporters.Editor.ModelExporter.ExportObjects (filename, selected) as string;
229232
Debug.unityLogger.logEnabled = true;

0 commit comments

Comments
 (0)