Unity 一键制作预制体,一键修改预制体

Posted Mark_源

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unity 一键制作预制体,一键修改预制体相关的知识,希望对你有一定的参考价值。

 生成 、修改预制体属性 所用到的API

PrefabUtility.SaveAsPrefabAsset(GameObject instanceRoot, string assetPath);

PrefabUtility.SavePrefabAsset(GameObject asset);

AssetDatabase.LoadAssetAtPath(string assetPath, Type type);

AssetDatabase.SaveAssets();

AssetDatabase.Refresh();

具体用法:

一、制作预制体

获取预制体所需源文件路径(源文件最好放在Resources文件夹内方便加载,等制作完成后可以移动到合适位置)

主要方法:

1)、获取路径下的所有文件夹

        /// <summary>
        /// 获取路径下的所有文件夹
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        private string[] GetAllFolder(string path)
        
            try
            

                string[] dirs = Directory.GetDirectories(path, "*");
                string[] folderName = new string[dirs.Length];
                for (int i = 0; i < dirs.Length; i++)
                
                    string file = dirs[i].Split('\\\\')[1];
                    folderName[i] = file;
                
                return folderName;
            
            catch (System.Exception)
            

                return null;
            


        

2)、获取文件下的文件

        /// <summary>
        /// 获取路径下的 Obj
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        private GameObject GetFileObj(string path)
        
            GameObject go = Resources.Load<GameObject>(path);
            if (go != null)
            
                return go;
            
            else
            
                Debug.Log(path);
                return null;
            

        

3)、实践:

  导入需要制作预制体的源文件,查看文件结构

    新建Editor 文件夹 并创建脚本 MakePrefab

 

public class MakePrefab : EditorWindow


    [MenuItem("Tools/MakePrefab")]
    public static void CreatePrefabWindow()
    
        EditorWindow window = EditorWindow.GetWindowWithRect(typeof(MakePrefab), new Rect(Screen.width / 3, Screen.height / 3, 800, 500), true, "MakePrefab");
        window.Show();
    

绘制面板

 private static string toSavePrefabPath = "Assets/Entities";


    private void OnGUI()
    

        EditorGUILayout.LabelField("预制体保存路径::", toSavePrefabPath, GUILayout.Width(110));
        toSavePrefabPath = EditorGUILayout.TextArea(toSavePrefabPath, GUILayout.Width(250));

        if (GUILayout.Button("转换预制体", GUILayout.Width(260)))
        
            ToPrefab();
        

        if (GUILayout.Button("修改预制体", GUILayout.Width(260)))
        
            ModifyPrefab(toSavePrefabPath);
        

    

效果展示

制作预制体

private void ToPrefab()
    
        string path = "Assets/Resources";
        string[] allFolder1 = GetAllFolder(path);
        if (allFolder1 == null)
            return;
        //循环次数取决于 ,源文件的目录结构 ,此处为 4 级结构
        for (int i = 0; i < allFolder1.Length; i++)
        
            string path2 = $"path/allFolder1[i]";
            string[] allFolder2 = GetAllFolder(path2);
            if (allFolder2 == null)
            
                return;
            
            for (int j = 0; j < allFolder2.Length; j++)
            
                string path3 = $"path2/allFolder2[j]";
                string[] allFolder3 = GetAllFolder(path3);
                if (allFolder3 == null)
                    return;
                for (int k = 0; k < allFolder3.Length; k++)
                

                    string path4 = $"path3/allFolder3[k]";
                    string[] allFolder4 = GetAllFolder(path4);
                    Debug.Log($"编号:k     allFolder3[k]文件下有        allFolder4.Length       个文件夹!");
                    if (allFolder4 == null)
                        return;

                    if (!Directory.Exists(toSavePrefabPath))
                    
                        Directory.CreateDirectory(toSavePrefabPath);
                    

                    for (int l = 0; l < allFolder4.Length; l++)
                    
                        string speedTree = $"path4/allFolder4[l]/allFolder4[l]";
                        string[] strs = Regex.Split(speedTree, path + "/", RegexOptions.IgnoreCase);
                        GameObject go = Instantiate(GetFileObj(strs[1]));
                        go.name = go.name.Replace("(Clone)", string.Empty);
                        //给预制体添加脚本,修改属性
                        //go.transform.tag = "Model";
                        if (go.GetComponent<BoxCollider>() == null)
                            go.AddComponent<BoxCollider>();

                        if (go.GetComponent<Rigidbody>() == null)
                            go.AddComponent<Rigidbody>();

                        go.GetComponent<Rigidbody>().isKinematic = true;

                        string modeName = allFolder4[l].Split('_')[0];

                        PrefabUtility.SaveAsPrefabAsset(go, $"toSavePrefabPath/modeName.prefab");
                        DestroyImmediate(go);
                    
                    AssetDatabase.Refresh();
                
            

        

    

效果展示

二、修改预制体:

当预制体中的某个属性设置错误的时候,比如 IsKinematic 属性时,需要统一修改这个属性

    /// <summary>
    /// 修改预制体
    /// </summary>
    /// <param name="path"></param>
    private void ModifyPrefab(string path)
    
        //获取文件下所有预制体文件
        DirectoryInfo info = new DirectoryInfo(path);
        FileInfo[] fileInfos = info.GetFiles("*.prefab");
        List<GameObject> prefabs = new List<GameObject>();
        foreach (var item in fileInfos)
        
            string paths = $"path/item.Name";
            GameObject prefab = AssetDatabase.LoadAssetAtPath(paths, typeof(GameObject)) as GameObject;
            prefabs.Add(prefab);
        
        //修改属性
        for (int i = 0; i < prefabs.Count; i++)
        
            if (prefabs[i].transform.childCount > 0 && prefabs[i].transform.GetChild(0) != null)
            
                if (prefabs[i].GetComponent<Rigidbody>() != null)
                
                    prefabs[i].GetComponent<Rigidbody>().isKinematic = false;                 
                    PrefabUtility.SavePrefabAsset(prefabs[i]);                  
                              
                      
        
        AssetDatabase.SaveAssets();
        AssetDatabase.Refresh();
    

效果展示

 

 这样所有的预制体都已经制作完成啦,以及后续修改里面的属性!

Unity 运行状态下动态保存 预制体/预制体上脚本参数

前言:在Unity游戏制作过程中为了方便策划调试保存 通常会让策划可以在游戏运行时直接保存调整好的预制体

在此背景下,出现了以下代码:

一.运行状态下动态保存预制体

代码:

public class ChangePrefabs : MonoBehaviour 
    public bool Save = false;
    public string Name;
    private string path;
    void Start() 
        Name = this.gameObject.name;
        path = string.Format("Assets/Model/0", Name.Replace("(Clone)", "")) ;
    

    void Update() 
        if(Save) 
            Save = false;
            PrefabUtility.SaveAsPrefabAsset(this.gameObject, path);
        
    

程序运行中修改预制体的上部球体的材质,然后点击Save,停止运行后 可以看到工程里的预制体也同样被改变了

1.把脚本挂在预制体上

2.修改预制体上部球体的材质

修改前:

修改后:

点击Save

 

3.停止运行后,工程中的预制体 上部球体变成了工程中修改的材质

二.运行状态下动态保存预制体上的脚本参数

代码:

public class ChangePrefabScript : MonoBehaviour 
    public bool Save = false;
    public string path;
    public string canChange;
    GameObject player;
    void Start() 
        player = Addressables.LoadAssetAsync<GameObject>(path).Result;
    

    // Update is called once per frame
    void Update() 
        if(Save) 
            Save = false;
            SerializedObject thisScript = new SerializedObject(this);
            if(player != null) 
                var oldChangePrefabScript = player.GetComponent<ChangePrefabScript>();
                SerializedObject oldScript = new SerializedObject(oldChangePrefabScript);
                SerializedProperty serializedProperty = thisScript.FindProperty("canChange");
                oldScript.CopyFromSerializedProperty(serializedProperty);
                oldScript.ApplyModifiedProperties();
            
        
    

程序运行中修改预制体上的脚本中的CanChange中的内容,然后点击Save,停止运行后 可以看到工程里的预制体上的脚本中的Can Change内容随之改变了

1.把脚本挂在预制体上

2.程序运行时改变Can Change的值 然后点击Save

3.程序停止运行后,找到预制体上的相应脚本查看 Can Change值已经变成修改值 

 

以上是关于Unity 一键制作预制体,一键修改预制体的主要内容,如果未能解决你的问题,请参考以下文章

Unity之自动生成预制体脚本

【Unity】把美术导入的动画和模型自动生成为程序所需要的预制体

Unity快速入门教程-详解预制体(Prefab)及其实例化Instantiate

Unity 运行状态下动态保存 预制体/预制体上脚本参数

Unity3D日常开发UI预制体的实例化实操演示

Unity3D日常开发UI预制体的实例化实操演示