FBX内のMeshを複製して独立したAssetとして保存する方法です。
Unity2018.1.4
ソースコード
早速ですがソースコードです。
using UnityEngine; using UnityEditor; using System.Linq; public class Example { /// <summary> /// FBX内のメッシュを複製する /// </summary> private static void DuplicateFbxMesh(GameObject fbx) { var fbxPath = AssetDatabase.GetAssetPath(fbx); if (!fbxPath.EndsWith(".fbx")) { throw new System.Exception("unsupported extension."); } var meshes = AssetDatabase.LoadAllAssetsAtPath(fbxPath).OfType<Mesh>().ToArray(); // 保存先のフォルダを作る var folderPath = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(fbxPath), "Mesh"); CreateFolder(folderPath); for (int i = 0; i < meshes.Count(); i++) { var mesh = meshes[i]; // FBX内のメッシュはアセット化できないので複製する var name = mesh.name; mesh = GameObject.Instantiate(mesh); mesh.name = name; var meshAssetPath = System.IO.Path.Combine(folderPath, mesh.name + ".asset"); CreateOrUpdate(mesh, meshAssetPath); } } /// <summary> /// 指定されたパスのフォルダを生成する /// </summary> private static void CreateFolder(string path) { var target = ""; var splitChars = new char[]{ System.IO.Path.DirectorySeparatorChar, System.IO.Path.AltDirectorySeparatorChar }; foreach (var dir in path.Split(splitChars)) { var parent = target; target = System.IO.Path.Combine(target, dir); if (!AssetDatabase.IsValidFolder(target)) { AssetDatabase.CreateFolder(parent, dir); } } } /// <summary> /// アセットがなければ新規作成し、すでにあれば更新する /// </summary> private static void CreateOrUpdate(Object newAsset, string assetPath) { var oldAsset = AssetDatabase.LoadAssetAtPath<Mesh>(assetPath); if (oldAsset == null) { AssetDatabase.CreateAsset(newAsset, assetPath); } else { EditorUtility.CopySerializedIfDifferent(newAsset, oldAsset); AssetDatabase.SaveAssets(); } } }
AssetImporterと組み合わせる
ついでにAssetImporterと組み合わせて、FBXをインポートした時に自動的にMeshが複製されるようにしてみます。
書いてるうちにあまりAssetImporterでやるべき処理じゃない気もしてきましたが一応・・
using UnityEngine; using UnityEditor; using System.Linq; using System.IO; public class ExampleProcessor : AssetPostprocessor { private const string MESH_FOLDER_NAME = "Mesh"; private void OnPreprocessModel() { var modelImporter = assetImporter as ModelImporter; // ModelImporterの設定はここで行う } private static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths) { System.Func<string, bool> isTarget = path => path.EndsWith(".fbx"); var targetImportedAssetPaths = importedAssets.Where(x => isTarget(x)).ToArray(); var targetDeletedAssetPaths = deletedAssets.Where(x => isTarget(x)).ToArray(); var targetMovedAssetPaths = movedAssets.Where(x => isTarget(x)).ToArray(); var targetMovedFromAssetPaths = movedFromAssetPaths.Where(x => isTarget(x)).ToArray(); // インポートされたアセットのメッシュを作成する foreach (var assetPath in targetImportedAssetPaths) { DuplicateFbxMesh(AssetDatabase.LoadAssetAtPath<GameObject>(assetPath)); } // 削除されたアセットのメッシュを削除する foreach (var assetPath in targetDeletedAssetPaths) { var directory = Path.GetDirectoryName(assetPath); directory = Path.Combine(directory, MESH_FOLDER_NAME); AssetDatabase.DeleteAsset(directory); } // 移動されたアセットのメッシュを移動する for (int i = 0; i < targetMovedAssetPaths.Length; i++) { var movedPath = targetMovedAssetPaths[i]; movedPath = Path.GetDirectoryName(movedPath); movedPath = Path.Combine(movedPath, MESH_FOLDER_NAME); var movedFromPath = targetMovedFromAssetPaths[i]; movedFromPath = Path.GetDirectoryName(movedFromPath); movedFromPath = Path.Combine(movedFromPath, MESH_FOLDER_NAME); AssetDatabase.MoveAsset(movedFromPath, movedPath); } } /// <summary> /// FBX内のメッシュを複製する /// </summary> private static void DuplicateFbxMesh(GameObject fbx) { var fbxPath = AssetDatabase.GetAssetPath(fbx); if (!fbxPath.EndsWith(".fbx")) { throw new System.Exception("unsupported extension."); } var meshes = AssetDatabase.LoadAllAssetsAtPath(fbxPath).OfType<Mesh>().ToArray(); // 保存先のフォルダを作る var folderPath = Path.Combine(Path.GetDirectoryName(fbxPath), MESH_FOLDER_NAME); CreateFolder(folderPath); for (int i = 0; i < meshes.Count(); i++) { var mesh = meshes[i]; EditorUtility.DisplayProgressBar("Duplicating Meshes", mesh.name + " of " + fbxPath, (float)i / meshes.Length); // FBX内のメッシュはアセット化できないので複製する var name = mesh.name; mesh = GameObject.Instantiate(mesh); mesh.name = name; var meshAssetPath = Path.Combine(folderPath, mesh.name + ".asset"); CreateOrUpdate(mesh, meshAssetPath); } EditorUtility.ClearProgressBar(); } /// <summary> /// 指定されたパスのフォルダを生成する /// </summary> private static void CreateFolder(string path) { var target = ""; var splitChars = new char[]{ Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar }; foreach (var dir in path.Split(splitChars)) { var parent = target; target = Path.Combine(target, dir); if (!AssetDatabase.IsValidFolder(target)) { AssetDatabase.CreateFolder(parent, dir); } } } /// <summary> /// アセットがなければ新規作成し、すでにあれば更新する /// </summary> private static void CreateOrUpdate(Object newAsset, string assetPath) { var oldAsset = AssetDatabase.LoadAssetAtPath<Mesh>(assetPath); if (oldAsset == null) { AssetDatabase.CreateAsset(newAsset, assetPath); } else { EditorUtility.CopySerializedIfDifferent(newAsset, oldAsset); AssetDatabase.SaveAssets(); } } }