@@ -963,24 +963,32 @@ SkinnedMeshRenderer unitySkin
963
963
var bones = unitySkin . bones ;
964
964
foreach ( var bone in bones )
965
965
{
966
- var fbxBone = MapUnityObjectToFbxNode [ bone . gameObject ] ;
967
- ExportTransform ( bone , fbxBone , newCenter : Vector3 . zero , TransformExportType . Local ) ;
966
+ // ignore null bones
967
+ if ( bone != null )
968
+ {
969
+ var fbxBone = MapUnityObjectToFbxNode [ bone . gameObject ] ;
970
+ ExportTransform ( bone , fbxBone , newCenter : Vector3 . zero , TransformExportType . Local ) ;
968
971
969
- // Cancel out the pre-rotation from the exported rotation
972
+ // Cancel out the pre-rotation from the exported rotation
970
973
971
- // Get prerotation
972
- var fbxPreRotationEuler = fbxBone . GetPreRotation ( FbxNode . EPivotSet . eSourcePivot ) ;
973
- // Convert the prerotation to a Quaternion
974
- var fbxPreRotationQuaternion = EulerToQuaternion ( fbxPreRotationEuler ) ;
975
- // Inverse of the prerotation
976
- fbxPreRotationQuaternion . Inverse ( ) ;
974
+ // Get prerotation
975
+ var fbxPreRotationEuler = fbxBone . GetPreRotation ( FbxNode . EPivotSet . eSourcePivot ) ;
976
+ // Convert the prerotation to a Quaternion
977
+ var fbxPreRotationQuaternion = EulerToQuaternion ( fbxPreRotationEuler ) ;
978
+ // Inverse of the prerotation
979
+ fbxPreRotationQuaternion . Inverse ( ) ;
977
980
978
- // Multiply LclRotation by pre-rotation inverse to get the LclRotation without pre-rotation applied
979
- var finalLclRotationQuat = fbxPreRotationQuaternion * EulerToQuaternion ( new FbxVector4 ( fbxBone . LclRotation . Get ( ) ) ) ;
981
+ // Multiply LclRotation by pre-rotation inverse to get the LclRotation without pre-rotation applied
982
+ var finalLclRotationQuat = fbxPreRotationQuaternion * EulerToQuaternion ( new FbxVector4 ( fbxBone . LclRotation . Get ( ) ) ) ;
980
983
981
- // Convert to Euler without axis conversion (Pre-rotation and LclRotation were already in Maya axis)
982
- // and update LclRotation
983
- fbxBone . LclRotation . Set ( ToFbxDouble3 ( QuaternionToEuler ( finalLclRotationQuat ) ) ) ;
984
+ // Convert to Euler without axis conversion (Pre-rotation and LclRotation were already in Maya axis)
985
+ // and update LclRotation
986
+ fbxBone . LclRotation . Set ( ToFbxDouble3 ( QuaternionToEuler ( finalLclRotationQuat ) ) ) ;
987
+ }
988
+ else
989
+ {
990
+ Debug . Log ( "Warning: One or more bones are null. Skeleton may not export correctly." ) ;
991
+ }
984
992
}
985
993
}
986
994
@@ -1043,16 +1051,25 @@ private bool ExportSkeleton (SkinnedMeshRenderer skinnedMesh, FbxScene fbxScene,
1043
1051
Dictionary < Transform , int > index = new Dictionary < Transform , int > ( ) ;
1044
1052
for ( int boneIndex = 0 ; boneIndex < bones . Length ; boneIndex ++ ) {
1045
1053
Transform unityBoneTransform = bones [ boneIndex ] ;
1046
- index [ unityBoneTransform ] = boneIndex ;
1054
+
1055
+ // ignore null bones
1056
+ if ( unityBoneTransform != null )
1057
+ {
1058
+ index [ unityBoneTransform ] = boneIndex ;
1059
+ }
1047
1060
}
1048
1061
1049
1062
skinnedMeshToBonesMap . Add ( skinnedMesh , bones ) ;
1050
1063
1051
1064
// Step 1: Set transforms
1052
1065
var boneInfo = new SkinnedMeshBoneInfo ( skinnedMesh , index ) ;
1053
1066
foreach ( var bone in bones ) {
1054
- var fbxBone = MapUnityObjectToFbxNode [ bone . gameObject ] ;
1055
- ExportBoneTransform ( fbxBone , fbxScene , bone , boneInfo ) ;
1067
+ // ignore null bones
1068
+ if ( bone != null )
1069
+ {
1070
+ var fbxBone = MapUnityObjectToFbxNode [ bone . gameObject ] ;
1071
+ ExportBoneTransform ( fbxBone , fbxScene , bone , boneInfo ) ;
1072
+ }
1056
1073
}
1057
1074
return true ;
1058
1075
}
@@ -1072,24 +1089,28 @@ private bool ExportSkin (SkinnedMeshRenderer skinnedMesh,
1072
1089
Dictionary < int , FbxCluster > boneCluster = new Dictionary < int , FbxCluster > ( ) ;
1073
1090
1074
1091
for ( int i = 0 ; i < skinnedMesh . bones . Length ; i ++ ) {
1075
- FbxNode fbxBoneNode = MapUnityObjectToFbxNode [ skinnedMesh . bones [ i ] . gameObject ] ;
1092
+ // ignore null bones
1093
+ if ( skinnedMesh . bones [ i ] != null )
1094
+ {
1095
+ FbxNode fbxBoneNode = MapUnityObjectToFbxNode [ skinnedMesh . bones [ i ] . gameObject ] ;
1076
1096
1077
- // Create the deforming cluster
1078
- FbxCluster fbxCluster = FbxCluster . Create ( fbxScene , "BoneWeightCluster" ) ;
1097
+ // Create the deforming cluster
1098
+ FbxCluster fbxCluster = FbxCluster . Create ( fbxScene , "BoneWeightCluster" ) ;
1079
1099
1080
- fbxCluster . SetLink ( fbxBoneNode ) ;
1081
- fbxCluster . SetLinkMode ( FbxCluster . ELinkMode . eNormalize ) ;
1100
+ fbxCluster . SetLink ( fbxBoneNode ) ;
1101
+ fbxCluster . SetLinkMode ( FbxCluster . ELinkMode . eNormalize ) ;
1082
1102
1083
- boneCluster . Add ( i , fbxCluster ) ;
1103
+ boneCluster . Add ( i , fbxCluster ) ;
1084
1104
1085
- // set the Transform and TransformLink matrix
1086
- fbxCluster . SetTransformMatrix ( fbxMeshMatrix ) ;
1105
+ // set the Transform and TransformLink matrix
1106
+ fbxCluster . SetTransformMatrix ( fbxMeshMatrix ) ;
1087
1107
1088
- FbxAMatrix fbxLinkMatrix = fbxBoneNode . EvaluateGlobalTransform ( ) ;
1089
- fbxCluster . SetTransformLinkMatrix ( fbxLinkMatrix ) ;
1108
+ FbxAMatrix fbxLinkMatrix = fbxBoneNode . EvaluateGlobalTransform ( ) ;
1109
+ fbxCluster . SetTransformLinkMatrix ( fbxLinkMatrix ) ;
1090
1110
1091
- // add the cluster to the skin
1092
- fbxSkin . AddCluster ( fbxCluster ) ;
1111
+ // add the cluster to the skin
1112
+ fbxSkin . AddCluster ( fbxCluster ) ;
1113
+ }
1093
1114
}
1094
1115
1095
1116
// set the vertex weights for each bone
@@ -1166,21 +1187,25 @@ private bool ExportBindPose (SkinnedMeshRenderer skinnedMesh, FbxNode fbxMeshNod
1166
1187
return false ;
1167
1188
}
1168
1189
for ( int i = 0 ; i < bones . Length ; i ++ ) {
1169
- FbxNode fbxBoneNode = MapUnityObjectToFbxNode [ bones [ i ] . gameObject ] ;
1170
-
1171
- // EvaluateGlobalTransform returns an FbxAMatrix (affine matrix)
1172
- // which has to be converted to an FbxMatrix so that it can be passed to fbxPose.Add().
1173
- // The hierarchy for FbxMatrix and FbxAMatrix is as follows:
1174
- //
1175
- // FbxDouble4x4
1176
- // / \
1177
- // FbxMatrix FbxAMatrix
1178
- //
1179
- // Therefore we can't convert directly from FbxAMatrix to FbxMatrix,
1180
- // however FbxMatrix has a constructor that takes an FbxAMatrix.
1181
- FbxMatrix fbxBindMatrix = new FbxMatrix ( fbxBoneNode . EvaluateGlobalTransform ( ) ) ;
1182
-
1183
- fbxPose . Add ( fbxBoneNode , fbxBindMatrix ) ;
1190
+ // ignore null bones
1191
+ if ( bones [ i ] != null )
1192
+ {
1193
+ FbxNode fbxBoneNode = MapUnityObjectToFbxNode [ bones [ i ] . gameObject ] ;
1194
+
1195
+ // EvaluateGlobalTransform returns an FbxAMatrix (affine matrix)
1196
+ // which has to be converted to an FbxMatrix so that it can be passed to fbxPose.Add().
1197
+ // The hierarchy for FbxMatrix and FbxAMatrix is as follows:
1198
+ //
1199
+ // FbxDouble4x4
1200
+ // / \
1201
+ // FbxMatrix FbxAMatrix
1202
+ //
1203
+ // Therefore we can't convert directly from FbxAMatrix to FbxMatrix,
1204
+ // however FbxMatrix has a constructor that takes an FbxAMatrix.
1205
+ FbxMatrix fbxBindMatrix = new FbxMatrix ( fbxBoneNode . EvaluateGlobalTransform ( ) ) ;
1206
+
1207
+ fbxPose . Add ( fbxBoneNode , fbxBindMatrix ) ;
1208
+ }
1184
1209
}
1185
1210
1186
1211
fbxPose . Add ( fbxMeshNode , new FbxMatrix ( fbxMeshNode . EvaluateGlobalTransform ( ) ) ) ;
0 commit comments