I’m trying to figure out the right way to write an asset importer or postprocessing script to import and reference additional texture files when importing a fbx file. Say I have a directory on my computer at the path “K:\GameDev\Assets\Models\Buildings\Example”, and in this folder I have the following files:
- building.fbx
- textures\concrete_basemap.tga
- textures\concrete_normal.tga
- textures\concrete_specular.tga
- textures\door_basemap.tga
- …
When I import the fbx file I want to be able to create the materials “concrete”, “door”, etc., and then check for the corresponding texture files and import them if they exist. So far I’ve been able to automate the material creation process using a custom AssetPostprocessor script with a OnAssignMaterialModel function:
private Material OnAssignMaterialModel(Material material, Renderer renderer)
{
// Check if we should import the asset.
if (ShouldImportObject() == false)
return null;
// Create the materials folder if it doesn't already exist.
if (AssetDatabase.IsValidFolder(Path.GetDirectoryName(this.assetPath) + "/materials") == false)
AssetDatabase.CreateFolder(Path.GetDirectoryName(this.assetPath), "materials");
// Create the textures folder if it doesn't already exist.
if (AssetDatabase.IsValidFolder(Path.GetDirectoryName(this.assetPath) + "/textures") == false)
AssetDatabase.CreateFolder(Path.GetDirectoryName(this.assetPath), "textures");
// Check if the material has already been created.
string materialPath = $"{Path.GetDirectoryName(this.assetPath)}/materials/{material.name}.mat";
Material meshMaterial = AssetDatabase.LoadAssetAtPath<Material>(materialPath);
if (meshMaterial != null)
return meshMaterial;
// Setup the material using our toon shader.
SetupMaterial(material);
AssetDatabase.CreateAsset(material, materialPath);
return material;
}
private void SetupMaterial(Material material)
{
// Format the
// Assign the toon shader.
material.shader = Shader.Find("UniToon/URP_2021_3/Lit");
// Check for basemap texture.
//string basemapTextureFsPath = this.
}
However, I seem to have hit two problems with this approach:
- The call to AssetDatabase.CreateAsset results in the following warning during import:
Calls to "AssetDatabase.CreateAsset" are restricted during asset importing. AssetDatabase.CreateAsset() was called as part of running an import. Please make sure this function is not called from ScriptedImporters or PostProcessors, as it is a source of non-determinism and will be disallowed in a forthcoming release.
So it seems like I’m not supposed to be doing this, or at the very least, this functionality may work now but may not work if I update to a newer version of Unity.
- There doesn’t seem to be any way to get the file path of the original fbx file that was imported which I could use to traverse the textures folder. This also loops back to issue #1 where calls to AssetDatabase.CreateAsset seem to be discouraged and removed in the future.
So I’m wondering if there’s other means for trying to do the following when importing an fbx file:
- Creating material assets for each material used in the fbx file.
- Importing additional textures in a “textures” folder that sits next to the fbx file on the file system (outside of the Unity project assets/data folder).
I don’t want to lose the functionality of the builtin fbx importer, just add additional functionality to the process. Packing the textures into the fbx file is not desirable as I’m using custom shaders that don’t exist in blender and for that reason I don’t even import the textures into blender in my work flow.