Skip to content

Commit 46ab2f1

Browse files
committed
refactor animation only export to separate bone and other object export
the ExportGameObjectAndParents function was handling both export of bones and regular objects, which was confusing. Separated it so the bones get exported first, then ExportGameObjectAndParents exports the remaining objects and makes sure all the objects are connected to one another. Also added a helper for creating a single FbxNode as the code was being duplicated a few times.
1 parent cab86c3 commit 46ab2f1

File tree

1 file changed

+114
-104
lines changed

1 file changed

+114
-104
lines changed

Packages/com.unity.formats.fbx/Editor/Scripts/FbxExporter.cs

Lines changed: 114 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -2530,6 +2530,39 @@ private string GetUniqueName(string name)
25302530
return uniqueName;
25312531
}
25322532

2533+
/// <summary>
2534+
/// Create a fbxNode from unityGo.
2535+
/// </summary>
2536+
/// <param name="unityGo"></param>
2537+
/// <param name="fbxScene"></param>
2538+
/// <returns>the created FbxNode</returns>
2539+
private FbxNode CreateFbxNode(GameObject unityGo, FbxScene fbxScene)
2540+
{
2541+
2542+
string fbxName = unityGo.name;
2543+
if (ExportOptions.UseMayaCompatibleNames)
2544+
{
2545+
fbxName = ConvertToMayaCompatibleName(unityGo.name);
2546+
if (ExportOptions.AllowSceneModification)
2547+
{
2548+
unityGo.name = fbxName;
2549+
}
2550+
}
2551+
2552+
FbxNode fbxNode = FbxNode.Create(fbxScene, GetUniqueName(fbxName));
2553+
2554+
// Default inheritance type in FBX is RrSs, which causes scaling issues in Maya as
2555+
// both Maya and Unity use RSrs inheritance by default.
2556+
// Note: MotionBuilder uses RrSs inheritance by default as well, though it is possible
2557+
// to select a different inheritance type in the UI.
2558+
// Use RSrs as the scaling inheritance instead.
2559+
fbxNode.SetTransformationInheritType(FbxTransform.EInheritType.eInheritRSrs);
2560+
2561+
MapUnityObjectToFbxNode[unityGo] = fbxNode;
2562+
2563+
return fbxNode;
2564+
}
2565+
25332566
/// <summary>
25342567
/// Creates an FbxNode for each GameObject.
25352568
/// </summary>
@@ -2543,18 +2576,7 @@ internal int ExportTransformHierarchy(
25432576
{
25442577
int numObjectsExported = exportProgress;
25452578

2546-
string fbxName = unityGo.name;
2547-
if (ExportOptions.UseMayaCompatibleNames) {
2548-
fbxName = ConvertToMayaCompatibleName (unityGo.name);
2549-
if (ExportOptions.AllowSceneModification)
2550-
{
2551-
unityGo.name = fbxName;
2552-
}
2553-
}
2554-
2555-
// create an FbxNode and add it as a child of parent
2556-
FbxNode fbxNode = FbxNode.Create (fbxScene, GetUniqueName (fbxName));
2557-
MapUnityObjectToFbxNode [unityGo] = fbxNode;
2579+
FbxNode fbxNode = CreateFbxNode(unityGo, fbxScene);
25582580

25592581
if (Verbose)
25602582
Debug.Log (string.Format ("exporting {0}", fbxNode.GetName ()));
@@ -2568,13 +2590,6 @@ internal int ExportTransformHierarchy(
25682590
return -1;
25692591
}
25702592

2571-
// Default inheritance type in FBX is RrSs, which causes scaling issues in Maya as
2572-
// both Maya and Unity use RSrs inheritance by default.
2573-
// Note: MotionBuilder uses RrSs inheritance by default as well, though it is possible
2574-
// to select a different inheritance type in the UI.
2575-
// Use RSrs as the scaling inheritance instead.
2576-
fbxNode.SetTransformationInheritType (FbxTransform.EInheritType.eInheritRSrs);
2577-
25782593
ExportTransform (unityGo.transform, fbxNode, newCenter, exportType);
25792594

25802595
fbxNodeParent.AddChild (fbxNode);
@@ -2641,48 +2656,20 @@ internal int ExportAnimationOnly(
26412656
TransformExportType exportType = TransformExportType.Local
26422657
){
26432658
AnimationOnlyExportData exportData = (AnimationOnlyExportData)data;
2644-
2645-
// export any bones
2646-
var skinnedMeshRenderers = unityGO.GetComponentsInChildren<SkinnedMeshRenderer> ();
26472659
int numObjectsExported = exportProgress;
26482660

2649-
foreach (var skinnedMesh in skinnedMeshRenderers) {
2650-
var boneArray = skinnedMesh.bones;
2651-
var bones = new HashSet<GameObject>();
2652-
var boneDict = new Dictionary<Transform, int> ();
2653-
2654-
for (int i = 0; i < boneArray.Length; i++) {
2655-
bones.Add (boneArray [i].gameObject);
2656-
boneDict.Add (boneArray [i], i);
2657-
}
2658-
2659-
// get the bones that are also in the export set
2660-
bones.IntersectWith (exportData.Objects);
2661-
2662-
// remove the exported bones from the export set
2663-
exportData.Objects.ExceptWith (bones);
2664-
2665-
var boneInfo = new SkinnedMeshBoneInfo (skinnedMesh, boneDict);
2666-
foreach (var bone in bones) {
2667-
FbxNode node;
2668-
if (!ExportGameObjectAndParents (
2669-
bone.gameObject, unityGO, fbxScene, out node, newCenter,
2670-
exportType, ref numObjectsExported, objectCount,
2671-
boneInfo
2672-
)) {
2673-
// export cancelled
2674-
return -1;
2675-
}
2676-
}
2677-
}
2678-
26792661
// make sure anim destination node is exported as well
26802662
var exportSet = exportData.Objects;
2681-
if (ExportOptions.AnimationDest && ExportOptions.AnimationSource) {
2682-
exportSet.Add (ExportOptions.AnimationDest.gameObject);
2663+
if (ExportOptions.AnimationDest && ExportOptions.AnimationSource)
2664+
{
2665+
exportSet.Add(ExportOptions.AnimationDest.gameObject);
26832666
}
26842667

2685-
// export everything else
2668+
// first export all the animated bones that are in the export set
2669+
// as only a subset of bones are exported, but we still need to make sure the bone transforms are correct
2670+
ExportAnimatedBones(unityGO, fbxScene, ref numObjectsExported, objectCount, exportData);
2671+
2672+
// export everything else and make sure all nodes are connected
26862673
foreach (var go in exportSet) {
26872674
FbxNode node;
26882675
if (!ExportGameObjectAndParents (
@@ -2731,6 +2718,57 @@ public SkinnedMeshBoneInfo(SkinnedMeshRenderer skinnedMesh, Dictionary<Transform
27312718
}
27322719
}
27332720

2721+
private bool ExportAnimatedBones (
2722+
GameObject unityGo,
2723+
FbxScene fbxScene,
2724+
ref int exportProgress,
2725+
int objectCount,
2726+
AnimationOnlyExportData exportData
2727+
)
2728+
{
2729+
var skinnedMeshRenderers = unityGo.GetComponentsInChildren<SkinnedMeshRenderer>();
2730+
foreach (var skinnedMesh in skinnedMeshRenderers)
2731+
{
2732+
var boneArray = skinnedMesh.bones;
2733+
var bones = new HashSet<GameObject>();
2734+
var boneDict = new Dictionary<Transform, int>();
2735+
2736+
for (int i = 0; i < boneArray.Length; i++)
2737+
{
2738+
bones.Add(boneArray[i].gameObject);
2739+
boneDict.Add(boneArray[i], i);
2740+
}
2741+
2742+
// get the bones that are also in the export set
2743+
bones.IntersectWith(exportData.Objects);
2744+
2745+
var boneInfo = new SkinnedMeshBoneInfo(skinnedMesh, boneDict);
2746+
foreach (var bone in bones)
2747+
{
2748+
FbxNode fbxNode;
2749+
// bone already exported
2750+
if (MapUnityObjectToFbxNode.TryGetValue(bone, out fbxNode))
2751+
{
2752+
continue;
2753+
}
2754+
fbxNode = CreateFbxNode(bone, fbxScene);
2755+
2756+
exportProgress++;
2757+
if (EditorUtility.DisplayCancelableProgressBar(
2758+
ProgressBarTitle,
2759+
string.Format("Creating FbxNode {0}/{1}", exportProgress, objectCount),
2760+
(exportProgress / (float)objectCount) * 0.5f))
2761+
{
2762+
// cancel silently
2763+
return false;
2764+
}
2765+
2766+
ExportBoneTransform(fbxNode, fbxScene, bone.transform, boneInfo);
2767+
}
2768+
}
2769+
return true;
2770+
}
2771+
27342772
/// <summary>
27352773
/// Exports the Gameobject and its ancestors.
27362774
/// </summary>
@@ -2744,61 +2782,34 @@ private bool ExportGameObjectAndParents(
27442782
Vector3 newCenter,
27452783
TransformExportType exportType,
27462784
ref int exportProgress,
2747-
int objectCount,
2748-
SkinnedMeshBoneInfo boneInfo = null)
2785+
int objectCount
2786+
)
27492787
{
2750-
// node already exists
2751-
if (MapUnityObjectToFbxNode.TryGetValue (unityGo, out fbxNode)) {
2752-
return true;
2753-
}
2754-
2755-
string fbxName = unityGo.name;
2756-
if (ExportOptions.UseMayaCompatibleNames) {
2757-
fbxName = ConvertToMayaCompatibleName (unityGo.name);
2758-
}
2759-
2760-
// create an FbxNode and add it as a child of parent
2761-
fbxNode = FbxNode.Create (fbxScene, GetUniqueName (fbxName));
2762-
MapUnityObjectToFbxNode [unityGo] = fbxNode;
2763-
2764-
exportProgress++;
2765-
if (EditorUtility.DisplayCancelableProgressBar (
2766-
ProgressBarTitle,
2767-
string.Format ("Creating FbxNode {0}/{1}", exportProgress, objectCount),
2768-
(exportProgress / (float)objectCount) * 0.5f)) {
2769-
// cancel silently
2770-
return false;
2771-
}
2772-
2773-
// Default inheritance type in FBX is RrSs, which causes scaling issues in Maya as
2774-
// both Maya and Unity use RSrs inheritance by default.
2775-
// Note: MotionBuilder uses RrSs inheritance by default as well, though it is possible
2776-
// to select a different inheritance type in the UI.
2777-
// Use RSrs as the scaling inhertiance instead.
2778-
fbxNode.SetTransformationInheritType (FbxTransform.EInheritType.eInheritRSrs);
2779-
2780-
// TODO: check if GO is a bone and export accordingly
2781-
var exportedBoneTransform = boneInfo != null?
2782-
ExportBoneTransform (fbxNode, fbxScene, unityGo.transform, boneInfo) : false;
2788+
// node doesn't exist so create it
2789+
if (!MapUnityObjectToFbxNode.TryGetValue(unityGo, out fbxNode))
2790+
{
2791+
fbxNode = CreateFbxNode(unityGo, fbxScene);
27832792

2784-
// export regular transform if we are not a bone or failed to export as a bone
2785-
if(!exportedBoneTransform){
2786-
ExportTransform (unityGo.transform, fbxNode, newCenter, exportType);
2787-
}
2793+
exportProgress++;
2794+
if (EditorUtility.DisplayCancelableProgressBar(
2795+
ProgressBarTitle,
2796+
string.Format("Creating FbxNode {0}/{1}", exportProgress, objectCount),
2797+
(exportProgress / (float)objectCount) * 0.5f))
2798+
{
2799+
// cancel silently
2800+
return false;
2801+
}
27882802

2789-
if (unityGo == rootObject || unityGo.transform.parent == null) {
2790-
fbxScene.GetRootNode ().AddChild (fbxNode);
2791-
return true;
2803+
ExportTransform(unityGo.transform, fbxNode, newCenter, exportType);
27922804
}
27932805

2794-
SkinnedMeshBoneInfo parentBoneInfo = null;
2795-
// if this object was a bone and it's parent is also a bone, then
2796-
// pass the bone info when exporting the parent recursively.
2797-
if (boneInfo != null && boneInfo.boneDict.ContainsKey(unityGo.transform.parent))
2806+
if (unityGo == rootObject || unityGo.transform.parent == null)
27982807
{
2799-
parentBoneInfo = boneInfo;
2808+
fbxScene.GetRootNode().AddChild(fbxNode);
2809+
return true;
28002810
}
28012811

2812+
// make sure all the nodes are connected and exported
28022813
FbxNode fbxNodeParent;
28032814
if (!ExportGameObjectAndParents (
28042815
unityGo.transform.parent.gameObject,
@@ -2808,8 +2819,7 @@ private bool ExportGameObjectAndParents(
28082819
newCenter,
28092820
TransformExportType.Local,
28102821
ref exportProgress,
2811-
objectCount,
2812-
parentBoneInfo
2822+
objectCount
28132823
)) {
28142824
// export cancelled
28152825
return false;

0 commit comments

Comments
 (0)