FBXからPrefabを新規作成、更新するためのスクリプトです。
FBXを更新すると関連するPrefabのコンポーネントをいちいち貼りなおさないといけなかったりするので、それを簡単にするためのツールです。
Unity2018.2
ソースコード
早速ですがソースコードです。
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEditor; using System.IO; using UnityEditorInternal; using System.Linq; public class FbxPrefabCreator { [MenuItem("Assets/Create/Prefab From Selected Fbx")] private static void CreatePrefabFromFbx() { var targetFbx = Selection.activeGameObject; CreatePrefabFromFbx(targetFbx); } private static void CreatePrefabFromFbx(GameObject sourceFbx) { var sourcePath = AssetDatabase.GetAssetPath(sourceFbx); var savePath = Path.GetDirectoryName(sourcePath); var extension = "prefab"; // FBXじゃなかったら処理しない if (!Path.HasExtension(sourcePath) || Path.GetExtension(sourcePath) != ".fbx") { throw new System.Exception("Source is not fbx."); } // ファイル保存パネルを表示 var defaultFileName = Path.GetFileNameWithoutExtension(sourcePath) + "_" + extension; savePath = EditorUtility.SaveFilePanelInProject("Save Asset", defaultFileName, extension, "", savePath); // 保存パスが不正だったら処理しない if (string.IsNullOrEmpty(savePath)) { throw new System.Exception("Path to save is invalid."); } // Prefabのインスタンスを作成 var tmpInstance = GameObject.Instantiate(sourceFbx); // インスタンスを編集したければここで行う { } var targetPrefab = AssetDatabase.LoadAssetAtPath<GameObject>(savePath); if (targetPrefab == null) { // Prefab未生成だったら新規作成 PrefabUtility.CreatePrefab(savePath, tmpInstance); } else { // Prefab生成済みだった場合は生成済みのPrefabからコンポーネントをコピペして上書き foreach (var oldObject in targetPrefab.GetComponentsInChildren<Transform>(true)) { // 同じ名前のGameObjectを同一のものとみなす var newObject = tmpInstance.transform.Find(oldObject.name); // ルートオブジェクトの場合だけは名前関係なく同一とみなす if (oldObject == targetPrefab.transform.root) { newObject = tmpInstance.transform.root; } if (newObject == null) { continue; } // 既存のオブジェクトのコンポーネントのうち、新しいオブジェクトに無いものをコピペする var components = oldObject.GetComponents<Component>(); var componentTypes = components.Select(x => x.GetType()).Distinct(); foreach (var componentType in componentTypes) { // 同じ種類のコンポーネントがアタッチされていなかったら全てアタッチする if (newObject.GetComponents(componentType).Length == 0) { foreach (var component in components.Where(y => y.GetType() == componentType)) { ComponentUtility.CopyComponent(component); ComponentUtility.PasteComponentAsNew(newObject.gameObject); } } } } PrefabUtility.ReplacePrefab(tmpInstance, targetPrefab, ReplacePrefabOptions.ConnectToPrefab); } GameObject.DestroyImmediate(tmpInstance); } }
Prefabを更新する際には同じ名前のGameObjectを同一のものとみなし、貼られているコンポーネントをコピーします。
大体のケースはこんな感じの実装で問題ないのではないかと思います。
使い方
Fbxを右クリック > Create > Prefab From Selected Fbxを選択することで使用します。