Last active
April 20, 2025 22:33
-
-
Save SorraTheOrc/251c49c435cc52dff3553daba5d9fa12 to your computer and use it in GitHub Desktop.
Apply a material to all models in a folder.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
using UnityEditor; | |
namespace WizardsCode.Models { | |
/// <summary> | |
/// A custom Unity Editor window that allows users to find and process 3D models in a specified folder, | |
/// applying a selected material to all renderers within the models. | |
/// | |
/// This is useful when an asset is published in which the models do not have materials applied. For things | |
/// like terrain details this is problematic and since there are usually many models for details the manual | |
/// process of applying the material can be tedious. This editor window automates that process in a single click. | |
/// | |
/// However, it is currently limited to models that are in the same folder as the material. That is, it will only | |
/// truly be useful when the models are using a material atlas. | |
/// </summary> | |
public class ModelMaterialSetterEditor : EditorWindow | |
{ | |
/// <summary> | |
/// The folder path where the models are located. This is selected by the user through the editor interface. | |
/// </summary> | |
private string folderPath; | |
/// <summary> | |
/// The material to be applied to the models' renderers. This is selected by the user through the editor interface. | |
/// </summary> | |
private Material selectedMaterial; | |
/// <summary> | |
/// Displays the "Model Material Finder" window in the Unity Editor. | |
/// </summary> | |
[MenuItem("Wizards Code/Model Material Finder")] | |
public static void ShowWindow() | |
{ | |
GetWindow<ModelMaterialSetterEditor>("Model Material Finder"); | |
} | |
/// <summary> | |
/// Draws the GUI for the editor window, allowing the user to select a folder, choose a material, | |
/// and process the models in the folder. | |
/// </summary> | |
private void OnGUI() | |
{ | |
EditorGUILayout.LabelField("Select Folder and Material", EditorStyles.boldLabel); | |
// Folder path field | |
EditorGUILayout.BeginHorizontal(); | |
EditorGUILayout.LabelField("Folder Path", GUILayout.Width(75)); | |
folderPath = AssetDatabase.GUIDToAssetPath( | |
AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath( | |
EditorGUILayout.ObjectField( | |
AssetDatabase.LoadAssetAtPath<Object>(folderPath), typeof(DefaultAsset), false) as DefaultAsset)) | |
); | |
EditorGUILayout.EndHorizontal(); | |
if (string.IsNullOrEmpty(folderPath)) | |
{ | |
EditorGUILayout.HelpBox("Please select a folder containing the models.", MessageType.Warning); | |
return; | |
} | |
// Material field | |
selectedMaterial = (Material)EditorGUILayout.ObjectField("Material", selectedMaterial, typeof(Material), false); | |
if (selectedMaterial == null) | |
{ | |
EditorGUILayout.HelpBox("Please select a material to apply to the models.", MessageType.Warning); | |
return; | |
} | |
EditorGUILayout.Space(); | |
if (GUILayout.Button("Process Models")) | |
{ | |
if (string.IsNullOrEmpty(folderPath) || selectedMaterial == null) | |
{ | |
EditorUtility.DisplayDialog("Error", "Please select a folder and a material before processing.", "OK"); | |
} | |
else | |
{ | |
ProcessModels(); | |
} | |
} | |
} | |
void ProcessModels() | |
{ | |
int count = 0; | |
string[] guids = AssetDatabase.FindAssets("t:Model", new[] { folderPath }); | |
foreach (string guid in guids) | |
{ | |
string assetPath = AssetDatabase.GUIDToAssetPath(guid); | |
EditorUtility.DisplayProgressBar("Processing Models", $"Processing {assetPath}", (float)count / guids.Length); | |
GameObject model = AssetDatabase.LoadAssetAtPath<GameObject>(assetPath); | |
if (model != null) | |
{ | |
Renderer[] renderers = model.GetComponentsInChildren<Renderer>(); | |
foreach (var renderer in renderers) | |
{ | |
renderer.sharedMaterial = selectedMaterial; | |
} | |
EditorUtility.SetDirty(model); | |
count++; | |
} | |
} | |
EditorUtility.ClearProgressBar(); | |
if (count > 0) { | |
EditorUtility.DisplayDialog("Processing Complete", $"{count} of {guids.Length} models were processed and updated with the selected material.", "OK"); | |
AssetDatabase.SaveAssets(); | |
AssetDatabase.Refresh(); | |
} | |
else { | |
EditorUtility.DisplayDialog("No Models Found", "No models were found in the selected folder.", "OK"); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment