Skip to content

Commit e1dc3b4

Browse files
authored
SkinnedMeshExtractor
1 parent 7fe8927 commit e1dc3b4

14 files changed

Lines changed: 1393 additions & 0 deletions

Editor/FbxExporter.cs

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
using System;
2+
using System.Reflection;
3+
using UnityEditor;
4+
using UnityEngine;
5+
6+
namespace MeshTools
7+
{
8+
9+
public enum FbxRigType
10+
{
11+
12+
MatchSource,
13+
Humanoid,
14+
Generic,
15+
Legacy,
16+
None,
17+
}
18+
19+
internal static class FbxExporter
20+
{
21+
public static bool IsFbxPackageInstalled()
22+
{
23+
return Type.GetType(
24+
"UnityEditor.Formats.Fbx.Exporter.ModelExporter, Unity.Formats.Fbx.Editor") != null;
25+
}
26+
27+
public static void TryExportFbx(GameObject go, string fbxPath)
28+
{
29+
30+
var exporterType = Type.GetType(
31+
"UnityEditor.Formats.Fbx.Exporter.ModelExporter, Unity.Formats.Fbx.Editor");
32+
if (exporterType == null)
33+
{
34+
Debug.LogWarning("FBX export skipped: Unity FBX Exporter package not installed. Install 'com.unity.formats.fbx' from Package Manager.");
35+
return;
36+
}
37+
38+
try
39+
{
40+
var method = exporterType.GetMethod("ExportObject",
41+
BindingFlags.Public | BindingFlags.Static,
42+
null,
43+
new Type[] { typeof(string), typeof(UnityEngine.Object) },
44+
null);
45+
if (method == null)
46+
{
47+
Debug.LogWarning("FBX export skipped: FBX Exporter found but ExportObject(string, Object) method signature missing.");
48+
return;
49+
}
50+
51+
method.Invoke(null, new object[] { fbxPath, go });
52+
}
53+
catch (Exception e)
54+
{
55+
Debug.LogWarning("FBX export threw: " + e.GetType().Name + " — " + e.Message);
56+
}
57+
}
58+
59+
60+
public static ModelImporterAnimationType? DetectSourceRigType(GameObject source)
61+
{
62+
if (source == null) return null;
63+
64+
var animator = source.GetComponentInChildren<Animator>(true);
65+
66+
67+
if (animator != null && animator.avatar != null)
68+
{
69+
var avatarPath = AssetDatabase.GetAssetPath(animator.avatar);
70+
var importer = AssetImporter.GetAtPath(avatarPath) as ModelImporter;
71+
if (importer != null) return importer.animationType;
72+
}
73+
74+
foreach (var smr in source.GetComponentsInChildren<SkinnedMeshRenderer>(true))
75+
{
76+
if (smr.sharedMesh == null) continue;
77+
var path = AssetDatabase.GetAssetPath(smr.sharedMesh);
78+
var importer = AssetImporter.GetAtPath(path) as ModelImporter;
79+
if (importer != null) return importer.animationType;
80+
}
81+
82+
foreach (var mf in source.GetComponentsInChildren<MeshFilter>(true))
83+
{
84+
if (mf.sharedMesh == null) continue;
85+
var path = AssetDatabase.GetAssetPath(mf.sharedMesh);
86+
var importer = AssetImporter.GetAtPath(path) as ModelImporter;
87+
if (importer != null) return importer.animationType;
88+
}
89+
90+
91+
if (animator != null && animator.avatar != null && animator.avatar.isValid)
92+
{
93+
return animator.avatar.isHuman
94+
? ModelImporterAnimationType.Human
95+
: ModelImporterAnimationType.Generic;
96+
}
97+
98+
return null;
99+
}
100+
101+
102+
public static bool SetRigTypeOnAsset(string fbxAssetPath, FbxRigType rigType, ModelImporterAnimationType fallbackIfNoSource = ModelImporterAnimationType.Generic)
103+
{
104+
if (string.IsNullOrEmpty(fbxAssetPath)) return false;
105+
106+
AssetDatabase.ImportAsset(fbxAssetPath, ImportAssetOptions.ForceUpdate);
107+
108+
var importer = AssetImporter.GetAtPath(fbxAssetPath) as ModelImporter;
109+
if (importer == null)
110+
{
111+
Debug.LogWarning("Rig type setup skipped: no ModelImporter at " + fbxAssetPath);
112+
return false;
113+
}
114+
115+
ModelImporterAnimationType target;
116+
switch (rigType)
117+
{
118+
case FbxRigType.Humanoid: target = ModelImporterAnimationType.Human; break;
119+
case FbxRigType.Generic: target = ModelImporterAnimationType.Generic; break;
120+
case FbxRigType.Legacy: target = ModelImporterAnimationType.Legacy; break;
121+
case FbxRigType.None: target = ModelImporterAnimationType.None; break;
122+
default: target = fallbackIfNoSource; break;
123+
}
124+
125+
if (importer.animationType != target)
126+
{
127+
importer.animationType = target;
128+
if (target == ModelImporterAnimationType.Human)
129+
{
130+
//Let Unity auto generate the avatar from this FBXs own skeleton
131+
importer.avatarSetup = ModelImporterAvatarSetup.CreateFromThisModel;
132+
}
133+
importer.SaveAndReimport();
134+
}
135+
136+
return true;
137+
}
138+
}
139+
}

Editor/FbxExporter.cs.meta

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)