Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
11
Question by taoa · Dec 22, 2010 at 01:15 PM · editor-scriptingassetmodelfbx

[Editor scripting] How to save a script generated mesh as an asset/FBX?

Hello,

I've got an editor script that will generate some meshes, and I would like to be able to save these meshes as assets (FBX files)

This:

AssetDatabase.CreateAsset( [mesh object here], [path to asset] );

doesn't work.

Trying to add a ModelImporter object doesn't either, and besides, if I use an FBX extension to save the asset, it will be automatically processed as a model asset, but still won't work.

Thanks.

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

4 Replies

· Add your reply
  • Sort: 
avatar image
10
Best Answer

Answer by Mike 3 · Dec 22, 2010 at 01:24 PM

Use SaveAssets to commit the changes. Also - make sure that path to asset is relative to the project (not relative to Assets), and the extension is .asset

AssetDatabase.CreateAsset( [mesh object here], [path to asset] );
AssetDatabase.SaveAssets();

Or, as the comments say - save your meshes as obj files so that they get imported as model assets :D

Comment
Add comment · Show 9 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image taoa · Dec 22, 2010 at 01:26 PM 0
Share

Yeah I did that actually, but I still end up with some random data the FBX importer doesn't seem to recognize.

avatar image Mike 3 · Dec 22, 2010 at 01:30 PM 1
Share

Ah, right, that's not going to work no, you're just saving the unity serialized data that way. What you could try is the obj exporter using the $$anonymous$$esh you already have: http://www.unifycommunity.com/wiki/index.php?title=ObjExporter

avatar image taoa · Dec 22, 2010 at 01:41 PM 1
Share

Thanks $$anonymous$$ike, but, again, that's not my ultimate goal :) The only reason I want my generated mesh to be a FBX is to invoke the 'Generate Lightmap UVs' feature on it, so that I can lightmap a scene populated with the models I have generated. Devious, I know. But I tried to copy UV2s from the original models I construct my new models from, alas to no avail.

avatar image taoa · Dec 22, 2010 at 01:57 PM 0
Share

Correction: I got the meshes to be saved as such (they are pure 'mesh' objects), but of course, not being considered as models from Unity, I can't do to them things I can on models, such as generating lightmap uvs.

avatar image Mike 3 · Dec 22, 2010 at 02:12 PM 2
Share

Try this one ins$$anonymous$$d: http://www.unifycommunity.com/wiki/index.php?title=ObjExporterColorUvs then convert to fbx with an external program?

Show more comments
avatar image
36

Answer by Pharan · Apr 20, 2015 at 03:13 AM

I wrote a small editor script that adds a context menu item to the MeshFilter component. It will allow you to save the mesh in the MeshFilter as a .asset file, which you can drag into any GameObject with a MeshRenderer and MeshFilter and it will work.

https://github.com/pharan/Unity-MeshSaver/blob/master/MeshSaver/Editor/MeshSaverEditor.cs

You can also check the code to see how it was done.

Comment
Add comment · Show 8 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image malkere · Oct 24, 2015 at 04:15 PM 0
Share

much appreciated

avatar image helix · Nov 11, 2016 at 04:29 PM 0
Share

Thank you for this!

avatar image CJ-Clark · Apr 30, 2017 at 06:02 AM 1
Share

Wow, this was perfect! We learn something new everyday! Thanks for putting this together!

avatar image bhunterd · Oct 07, 2017 at 07:33 AM 0
Share

Thank you.

avatar image elenzil · Jun 08, 2018 at 08:39 PM 0
Share

great addition.

Show more comments
avatar image
5

Answer by femi · Jan 02, 2011 at 10:55 PM

There is a method not involving generation of intermediate files: have a prefab template that looks almost ready and only misses a mesh. You can then either save your mesh into this prefab and assign it to MeshFilter's sharedMesh or (useful if you want to generate multiple meshes into identical prefab) go something like:

// All generated models will be structured after this template string modelTemplate = "Assets/Templates/Model.prefab";

void Generate(string prefabPath) { // clone the model template Object templatePrefab = AssetDatabase.LoadAssetAtPath(modelTemplate, typeof(GameObject)); GameObject template = (GameObject)EditorUtility.InstantiatePrefab(templatePrefab);

 // this way links will persist when we regenerate the mesh
 Object prefab = AssetDatabase.LoadAssetAtPath(prefabPath, typeof(GameObject));
 if (!prefab) {
     prefab = EditorUtility.CreateEmptyPrefab( prefabPath );
 }

 // sort of the same...
 Mesh mesh = (Mesh)AssetDatabase.LoadAssetAtPath(prefabPath, typeof(Mesh));
 if (!mesh) {
     mesh = new Mesh();
     mesh.name = name;
     AssetDatabase.AddObjectToAsset (mesh, prefabPath);
 } else {
     mesh.Clear();
 }
 // generate your mesh in place
 BlaBlaBla(mesh);
 // assume that MeshFilter is already there. could check and AddComponent
 template.GetComponent<MeshFilter>().sharedMesh = mesh;

 // make sure 
 EditorUtility.ReplacePrefab(template, prefab, ReplacePrefabOptions.ReplaceNameBased);
 // get rid of the temporary object (otherwise it stays over in scene)
 Object.DestroyImmediate(template);

}

This is not generalized enough yet (contains a call to BlaBlaBla :-) - mesh generation function), you really should pass some sort of generator object to this function or something like that. It's because I adapted this snippet from my working code that does something slightly different. Now that I realize that it's generalizable I'll probably refactor it next time I have some time to kill.

This code makes sure that if you've instantiated your models already and decide to regenerate the mesh prefab link will stay intact. On the other hand, model is not linked to the template, if you change the template you will have to regenerate all models you have (and their instances will get updated then).

Comment
Add comment · Show 4 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image taoa · Jan 03, 2011 at 09:35 AM 0
Share

Thanks atm. However I don't see how this will save the mesh as a $$anonymous$$odel. It will create a prefab asset where you'll put you mesh in, but that won't allow you to invoke on the mesh things you can do to $$anonymous$$odels, such as recalculate normals or tangents or generate secondary UVs for lightmapping (my ultimate goal). Of course, please correct me if I'm wrong! ^^

avatar image femi · Jan 03, 2011 at 08:47 PM 0
Share

Ah, do you mean you want to somehow pass it to $$anonymous$$odelImporter? Sorry then, I misunderstood: I gues I see my own problems in other people's questions :-) But: in my script, after the meshes are saved in the prefab I see unity's own ProgressBar dialog appearing saying "importing blablabla.prefab". I wonder if model importers are called with it... Let me test.

avatar image femi · Jan 03, 2011 at 08:50 PM 0
Share

nope they don't :-)

avatar image ThePersister · Jun 25, 2015 at 11:38 AM 0
Share

Holy shit xD I love you femi, it took me a long while of messing around to get your solution to work for my case, but in the end I managed to do it!

Thank you so much for making a key part of my game possible!! :)

avatar image
2

Answer by JohannesMP · Jul 26, 2018 at 07:31 AM

I had some old .asset files of Mesh data that I wanted to make accessible for external editing as FBX files. I was able to use the SDK provided in https://assetstore.unity.com/packages/essentials/101408 to write my own context menu option for Mesh .asset files. The SDK enabled a large amount of control, such as saving as ascii or binary format , changing the scale and axis orientation, etc.


You can use the ExtractToFBX function in the code below to save any dynamically generated mesh (you must provide a filepath) or serialized Mesh asset file to an FBX:

 using System.IO;
 using UnityEngine;
 using UnityEditor;
 using Unity.FbxSdk;
 using FbxExporters.Editor;
 
 // Place in 'Editor' folder
 public static class ExtractMeshToFBX
 {
     // true: fbx file is easy-to-debug ascii, false: fbx file is binary.
     static bool saveFbxAsAscii = false;
 
     // The preferred axis system for the exported fbx file
     static FbxAxisSystem fbxAxisSystem = FbxAxisSystem.Max;
     // The preferred units of the exported fbx file
     static FbxSystemUnit fbxUnit = FbxSystemUnit.m;
 
     static string fbxFileTitle       = "TITLE HERE";
     static string fbxFileSubject     = "SUBJECT HERE";
     static string fbxFileComment     = "COMMENT HERE";
     static string fbxFileKeywords    = "KEYWORDS HERE";
     static string fbxFileAuthor      = "AUTHOR HERE";
     static string fbxFileRevision    = "1.0";
     static string fbxFileApplication = "Unity FBX SDK";
 
 
     [MenuItem("Assets/Extract to FBX", validate = true)]
     public static bool MenuExtractToFBXValidate()
     {
         if (Selection.activeObject == null)
             return false;
         return Selection.activeObject.GetType() == typeof(Mesh);
     }
 
     [MenuItem("Assets/Extract to FBX")]
     public static void MenuExtractToFBX()
     {
         // We assume validation worked and this is always defined.
         Mesh mesh = Selection.activeObject as Mesh;
 
         // Set up paths
         string meshFilePath = AssetDatabase.GetAssetPath(mesh);
         string meshDirectory = Path.GetDirectoryName(meshFilePath);
 
         string filename = Path.GetFileNameWithoutExtension(meshFilePath) + ".fbx";
         string filePath = Path.Combine(meshDirectory, filename);
 
         ExtractToFBX(mesh, filePath);
     }
 
     public static void ExtractToFBX(Mesh mesh, string filePath)
     {
         // Make a temporary copy of the mesh to modify it
         Mesh tempMesh = Object.Instantiate(mesh);
         tempMesh.name = mesh.name;
 
         // If meters, divide by 100 since default is cm. Assume centered at origin.
         if (fbxUnit == FbxSystemUnit.m)
         {
             Vector3[] vertices = tempMesh.vertices;
             for (int i = 0; i < vertices.Length; ++i)
                 vertices[i] /= 100.0f;
             tempMesh.vertices = vertices;
         }
         // You could handle other SystemUnits here
 
         // FBX Manager
         FbxManager manager = FbxManager.Create();
         manager.SetIOSettings(FbxIOSettings.Create(manager, Globals.IOSROOT));
 
         // FBX Exporter
         FbxExporter fbxExporter = FbxExporter.Create(manager, "Exporter");
 
         // Binary
         int fileFormat = -1;
         // Ascii
         if (saveFbxAsAscii)
             fileFormat = manager.GetIOPluginRegistry().FindWriterIDByDescription("FBX ascii (*.fbx)");
 
         fbxExporter.Initialize(filePath, fileFormat, manager.GetIOSettings());
         fbxExporter.SetFileExportVersion("FBX201400");
 
         // FBX Scene
         FbxScene fbxScene = FbxScene.Create(manager, "Scene");
         FbxDocumentInfo sceneInfo = FbxDocumentInfo.Create(manager, "SceneInfo");
 
         // Set up scene info
         sceneInfo.mTitle    = fbxFileTitle;
         sceneInfo.mSubject  = fbxFileSubject;
         sceneInfo.mComment  = fbxFileComment;
         sceneInfo.mAuthor   = fbxFileAuthor;
         sceneInfo.mRevision = fbxFileRevision;
         sceneInfo.mKeywords = fbxFileKeywords;
         sceneInfo.Original_ApplicationName.Set(fbxFileApplication);
         sceneInfo.LastSaved_ApplicationName.Set(fbxFileApplication);
         fbxScene.SetSceneInfo(sceneInfo);
 
         // Set up Global settings
         FbxGlobalSettings globalSettings = fbxScene.GetGlobalSettings();
         globalSettings.SetSystemUnit(fbxUnit);
         globalSettings.SetAxisSystem(fbxAxisSystem);
 
         FbxNode modelNode = FbxNode.Create(fbxScene, tempMesh.name);
         // Add mesh to a node in the scene
         using (ModelExporter modelExporter = new ModelExporter())
         {
             if (!modelExporter.ExportMesh(tempMesh, modelNode))
                 Debug.LogError("Problem Exporting Mesh");
         }
         // add the model to the scene
         fbxScene.GetRootNode().AddChild(modelNode);
 
         // Finally actually save the scene
         bool sceneSuccess = fbxExporter.Export(fbxScene);
         AssetDatabase.Refresh();
 
         // clean up temporary model
         if (Application.isPlaying)
             Object.Destroy(tempMesh);
         else
             Object.DestroyImmediate(tempMesh);
     }
 }

The code worked even on 2017.1 despite the above package requiring 2017.3, after first downloading the package in a later version and then manually moving the DLLs. The dependency on 2017.3 is only due to their custom UI, which this code does not use.


If you want to include materials in the fbx you can easily modify the function to pass in materials which can be passed in as an argument to modelExporter.ExportMesh.

Comment
Add comment · Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Harinezumi · Jul 26, 2018 at 07:41 AM 0
Share

Thanks for sharing this info and your code!

avatar image wangyd2 · Sep 11, 2020 at 08:23 AM 0
Share

Exactly the same situation, thanks a lot!

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

11 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Converting all MA files to FBX without changing GUIDs 2 Answers

How to make plane as tree leaf (2 side plane) like in GTA Vice City? 3 Answers

Different standing positions between drag/drop from Blender and import FBX 1 Answer

[Model] Imported Model - Resets to random rotation upon Play Mode 0 Answers

Why my imported fbx show semi transparent? 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges