본문 바로가기
Engine/UNITY

셰이더 일괄 교체 스크립트 제작

by tartist 2016. 6. 22.

프로젝트를 진행하면서 파티클 빌트인 셰이더들이 문제를 일으켜 일괄 변환해 줘야 하는 상황이 발생했습니다.

일일이 바꾸는 번거러움을 덜고자 제작한 스크립트 입니다.

 

 

1. 모바일 엔진 셰이더(바뀌어야할 셰이더 선택)

2. 바뀔 셰이더 선택

3. 대상 메터리얼들 선택(폴더 / 파일)

4. 대상 메터리얼중 1번과 동일 셰이더를 찾아 2번으로 바꿔줌~ 일괄 교체~

 

 

 

 

using UnityEngine;
using UnityEditor;
using System.Collections;
using System.Collections.Generic;
using System.IO;

public class MaterialControl : EditorWindow
{  
    public Shader shader1 = null;
    public Shader shader2 = null;

    public Color defaultColor;
    public Color tintColor = new Color(0.5F, 0.5F, 0.5F, 0.5F);

    Shader defaultShader = null;
    Shader changeShader = null;

    static float UIWidth = 500;
    static string OutputPath = string.Empty;
    
    bool IsError = false;
    List<string> tempPathList = new List<string>();
    List<string> InputPaths = new List<string>();
    
    string SearchPattern = "*.mat;*.*";


//    ShaderImporter texFormatSelected = ShaderImporter.GetAtPath;
//    TextureImporterFormat texFormatToChange = TextureImporterFormat.ETC2_RGBA8;

    [MenuItem("RK Tools/Art/MaterialControl")]
    static void InitWindow()
    {
        MaterialControl window = EditorWindow.GetWindow<MaterialControl>();
        window.position = new Rect(100f, 100f, UIWidth, 400f); //  초기 사이즈
        
        window.title = "Save Bundle";
        window.Show();        
    }
    
    void OnGUI()
    {
        FunctionManual();
        ShaderSetting();
        SelectOutPath();
        ClearSelectFolder();
        OutputSelectedFile();
        ConvertAtlasImage();
    }
    
    void FunctionManual()
    {
        GUILayout.Space(16);
        GUI.contentColor = Color.cyan;
        EditorGUILayout.LabelField("폴더를 선택해서 해당 폴더 내의 Shader를 변경합니다.");
        GUI.contentColor = Color.white;
        GUILayout.Space(8);
    }

    void ShaderSetting()
    {
        defaultShader = (Shader)EditorGUILayout.ObjectField("Original Shader", shader1, typeof(Shader));
        changeShader = (Shader)EditorGUILayout.ObjectField("Change Shader", shader2, typeof(Shader));

        defaultColor = EditorGUILayout.ColorField("Tint Color", tintColor);

        if (defaultShader != null)
        {
            shader1 = defaultShader;
            shader2 = changeShader;
            tintColor = defaultColor;
        }


    }

    string prevPath = Application.dataPath;


    void SelectOutPath()
    {
        if (GUILayout.Button("폴더 or 파일 선택"))
        {            
            GetAssetPath_Project();            
            Repaint();
        }
    }
    
    void GetAssetPath_Project()
    {        
        SelectionProcess();
        
        foreach (string path in tempPathList)
        {
            if (InputPaths.Exists(assetPath => (assetPath == path)))
                continue;
            InputPaths.Add(path);
        }        
        IsError = false;
    }
    
    bool SelectionProcess()
    {
        tempPathList.Clear();
        string AssetPath = string.Empty;
        foreach (UnityEngine.Object obj in Selection.objects)
        {
            AssetPath = AssetDatabase.GetAssetPath(obj);
            if (Directory.Exists(AssetPath))
            {
                tempPathList.AddRange(
                    AssetDatabase.FindAssets("t:Material", new string[] { AssetPath }));
                
                for (int i = 0; i < tempPathList.Count; ++i)
                {
                    tempPathList[i] = AssetDatabase.GUIDToAssetPath(tempPathList[i]);                    
                }
            }
            else if (File.Exists(AssetPath))
            {
                char[] separate = new char[] { ';', '*', '.' };
                foreach (string pattern in SearchPattern.Split(separate))
                {
                    if (AssetPath.ToLower().Contains(pattern))
                    {
                        tempPathList.Add(AssetPath.Replace(Application.dataPath, "Assets"));
                        break;
                    }
                }
            }
        }
        return true;
    }
    
    void ClearSelectFolder()
    {
        if (GUILayout.Button("선택 폴더 or 파일 해제"))
        {
            tempPathList.Clear();
            InputPaths.Clear();
        }
    }
    
    Vector2 scrollPos = new Vector2();
    void OutputSelectedFile()
    {
        EditorGUILayout.LabelField("선택 폴더");
        
        EditorGUILayout.BeginVertical("box", GUILayout.Width(UIWidth));
        scrollPos = EditorGUILayout.BeginScrollView(scrollPos, GUILayout.Width(UIWidth));
        
        foreach (string path in InputPaths)
        {
            EditorGUILayout.LabelField(path);
        }
        EditorGUILayout.EndScrollView();
        EditorGUILayout.EndVertical();
    }
    
    
    void ConvertAtlasImage()
    {        
        EditorGUILayout.BeginHorizontal();

        EditorGUILayout.EndHorizontal();

        EditorGUILayout.BeginVertical("box", GUILayout.Width(UIWidth));

        if(GUILayout.Button("선택된 메터리얼을 Change Shader로 변환"))
        {
            ChangeShaderToTargetMaterial();
        }
        EditorGUILayout.EndVertical ();
    }


    void ChangeShaderToTargetMaterial()
    {
        foreach (string path in InputPaths)
        {
            AssetDatabase.ImportAsset(path);

            Material material = (Material)AssetDatabase.LoadMainAssetAtPath(path);


            if (material.shader == shader1)
            {
                material.shader = shader2;

                material.SetColor("_TintColor", tintColor);
            }         
        }
    }
}