Skip to content

Commit 7994864

Browse files
authored
Merge pull request #168 from Unity-Technologies/UNI-26990-nested-FbxPrefab-fix
Uni 26990 nested fbx prefab fix
2 parents 1943399 + 54da83d commit 7994864

File tree

2 files changed

+55
-6
lines changed

2 files changed

+55
-6
lines changed

Assets/FbxExporters/Editor/FbxPrefabAutoUpdater.cs

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,11 @@ namespace FbxExporters
2323
/// </summary>
2424
public /*static*/ class FbxPrefabAutoUpdater : UnityEditor.AssetPostprocessor
2525
{
26+
#if UNITY_EDITOR
27+
public const string FBX_PREFAB_FILE = "/FbxPrefab.cs";
28+
#else
2629
public const string FBX_PREFAB_FILE = "/UnityFbxPrefab.dll";
27-
30+
#endif
2831
public static string FindFbxPrefabAssetPath()
2932
{
3033
// Find guids that are scripts that look like FbxPrefab.
@@ -1031,12 +1034,20 @@ void CompareAndUpdate()
10311034
// We could optimize this out if we had nothing to do, but then the
10321035
// OnUpdate handler wouldn't always get called, and that makes for
10331036
// confusing API.
1034-
var prefabInstance = UnityEditor.PrefabUtility.InstantiatePrefab(m_fbxPrefab.gameObject) as GameObject;
1035-
if (!prefabInstance) {
1037+
1038+
// This FbxPrefab may not be at the root of its prefab. We instantiate the root of the prefab, then
1039+
// we find the corresponding FbxPrefab.
1040+
var prefabRoot = UnityEditor.PrefabUtility.FindPrefabRoot(m_fbxPrefab.gameObject);
1041+
var prefabInstanceRoot = UnityEditor.PrefabUtility.InstantiatePrefab(prefabRoot) as GameObject;
1042+
if (!prefabInstanceRoot) {
10361043
throw new System.Exception(string.Format("Failed to instantiate {0}; is it really a prefab?",
10371044
m_fbxPrefab.gameObject));
10381045
}
1039-
var fbxPrefabInstance = prefabInstance.GetComponent<FbxPrefab>();
1046+
var fbxPrefabInstance = prefabInstanceRoot.GetComponentsInChildren<FbxPrefab>().FirstOrDefault(
1047+
fbxPrefab => UnityEditor.PrefabUtility.GetPrefabParent(fbxPrefab) == m_fbxPrefab);
1048+
if (!fbxPrefabInstance) {
1049+
throw new System.Exception(string.Format("Internal error: couldn't find the right FbxPrefab after instantiating."));
1050+
}
10401051

10411052
// Do ALL the things (potentially nothing).
10421053
var updatedObjects = updates.ImplementUpdates(fbxPrefabInstance);
@@ -1050,10 +1061,10 @@ void CompareAndUpdate()
10501061
fbxPrefabInstance.FbxHistory = newFbxRepString;
10511062

10521063
// Save the changes back to the prefab.
1053-
UnityEditor.PrefabUtility.ReplacePrefab(prefabInstance, m_fbxPrefab.transform);
1064+
UnityEditor.PrefabUtility.ReplacePrefab(prefabInstanceRoot, prefabRoot);
10541065

10551066
// Destroy the prefabInstance.
1056-
GameObject.DestroyImmediate(prefabInstance);
1067+
GameObject.DestroyImmediate(prefabInstanceRoot);
10571068
}
10581069

10591070
/// <summary>

Assets/FbxExporters/Editor/UnitTests/FbxPrefabTest.cs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,44 @@ public void TestTransformAndReparenting()
438438
Assert.That (original.transform.GetChild (0).GetChild (0).name, Is.EqualTo ("building3"));
439439
Assert.That (original.transform.GetChild (0).GetChild (0).localScale, Is.EqualTo (new Vector3 (.5f, .5f, .5f)));
440440
}
441+
442+
[Test]
443+
public void TestFbxPrefabNotAtRoot()
444+
{
445+
// UNI-23143: what happens if you have an FbxPrefab that's not at the root of its prefab?
446+
// Use case: table and chair are two separate fbx files, but we
447+
// combine them into one prefab.
448+
449+
// Create a cube fbx/prefab pair.
450+
var cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
451+
var cubeMesh = cube.GetComponent<MeshFilter>().sharedMesh;
452+
var cubePath = GetRandomFbxFilePath();
453+
var cubeInstance = ConvertToModel.Convert(cube, fbxFullPath: cubePath);
454+
var cubeName = cubeInstance.name;
455+
456+
// Create a prefab that has the cube as a child.
457+
// Test the test: make sure the structure is what we expect.
458+
var root = new GameObject("root");
459+
cubeInstance.transform.parent = root.transform;
460+
var rootPrefab = PrefabUtility.CreatePrefab(GetRandomPrefabAssetPath(), root);
461+
Assert.That(rootPrefab);
462+
Assert.That(rootPrefab.GetComponent<MeshFilter>(), Is.Null);
463+
Assert.That(rootPrefab.transform.GetChild(0).name == cubeName);
464+
Assert.AreEqual(24, rootPrefab.transform.GetChild(0).GetComponent<MeshFilter>().sharedMesh.vertexCount);
465+
466+
// Turn the cube into a quad by exporting over its fbx file.
467+
var quad = GameObject.CreatePrimitive(PrimitiveType.Quad);
468+
var quadMesh = quad.GetComponent<MeshFilter>().sharedMesh;
469+
ModelExporter.ExportObject(cubePath, quad);
470+
471+
// The actual test:
472+
// Make sure the rootPrefab has the structure we expect.
473+
// Before fixing the bug, the root of the prefab was destroyed and recreated, so the very first test here failed:
474+
Assert.That(rootPrefab);
475+
Assert.That(rootPrefab.GetComponent<MeshFilter>(), Is.Null);
476+
Assert.That(rootPrefab.transform.GetChild(0).name == cubeName);
477+
Assert.AreEqual(4, rootPrefab.transform.GetChild(0).GetComponent<MeshFilter>().sharedMesh.vertexCount);
478+
}
441479
}
442480

443481
public class FbxPrefabHelpersTest

0 commit comments

Comments
 (0)