Automatic material creation in Unreal Engine with Python
Potential task for automation is creation of material instances for a lot of meshes. For example, I use Houdini to generate a lot of assets procedurally – models with baked texture maps. Importing all these meshes, textures and creating material instances (based on common master material) and assigning respective textures for each model is repetitive and boring manual task.
Here is a sample python script that is meant to run on selected static meshes – it will automatically create Material Instance asset for each mesh based on its name and assign all textures also based on name. At the end it assigns newly created material instance to the mesh.
It expects textures to be named the same as static meshes, but with appropriate postfixes – “_basecolor”, “_normal” etc. It also expects standard folder structure:

import unreal def set_mi_texture(mi_asset, param_name, tex_path): if not unreal.EditorAssetLibrary.does_asset_exist(tex_path): unreal.log_warning("Can't find texture: " + tex_path) return False tex_asset = unreal.EditorAssetLibrary.find_asset_data( tex_path ).get_asset() return unreal.MaterialEditingLibrary.set_material_instance_texture_parameter_value(mi_asset, param_name, tex_asset) unreal.log("---------------------------------------------------") AssetTools = unreal.AssetToolsHelpers.get_asset_tools() MaterialEditingLibrary = unreal.MaterialEditingLibrary EditorAssetLibrary = unreal.EditorAssetLibrary base_mtl = unreal.EditorAssetLibrary.find_asset_data("/Game/Environment/Cave/Materials/M_CaveBase") #Iterate over selected meshes sel_assets = unreal.EditorUtilityLibrary.get_selected_assets() for sm_asset in sel_assets: if sm_asset.get_class().get_name() != "StaticMesh": continue #skip non-static-meshes asset_name = sm_asset.get_name() if asset_name.startswith("S_"): asset_name = asset_name[2:] # Store mesh name without prefix asset_folder = unreal.Paths.get_path(sm_asset.get_path_name()) base_folder = asset_folder[:-7] #get base folder (subtract "Meshes" from base path) mtl_folder = base_folder + "/Materials/" tex_folder = base_folder + "/Textures/" #create folder for materials if not exist if not unreal.EditorAssetLibrary.does_directory_exist(mtl_folder): unreal.EditorAssetLibrary.make_directory(mtl_folder) #name of material instance for this mesh mi_name = "MI_" + asset_name mi_full_path = mtl_folder + mi_name #Check if material instance already exists if EditorAssetLibrary.does_asset_exist(mi_full_path): mi_asset = EditorAssetLibrary.find_asset_data(mi_full_path).get_asset() unreal.log("Asset already exists") else: mi_asset = AssetTools.create_asset(mi_name, mtl_folder, unreal.MaterialInstanceConstant, unreal.MaterialInstanceConstantFactoryNew()) #set material instance parameters! MaterialEditingLibrary.set_material_instance_parent( mi_asset, base_mtl.get_asset() ) # set parent material MaterialEditingLibrary.set_material_instance_scalar_parameter_value( mi_asset, "Desaturation", 0.3) # set scalar parameter #find textures for this mesh set_mi_texture(mi_asset, "Base Color", tex_folder + "T_" + asset_name + "_basecolor") set_mi_texture(mi_asset, "Masks Map", tex_folder + "T_" + asset_name + "_masks") set_mi_texture(mi_asset, "Normal", tex_folder + "T_" + asset_name + "_normal") set_mi_texture(mi_asset, "BentNormal", tex_folder + "T_" + asset_name + "_Bentnormal") #set new material instance on static mesh sm_asset.set_material(0, mi_asset)
This might not be useful as is, but could serve as a code example when trying to do similar things with assets in UE.
Really helpful, thanks!
Thanks a lot! BTW, where do you find all the python documentations?
@Nian
Epic’s API documentation: https://docs.unrealengine.com/4.27/en-US/PythonAPI/
Thank you so much, Getting into unreal finally after years as a TA in 3ds max so helpful to have code snippets that work!