美文网首页
unity开发之辅助脚本(自动绑定prefab)

unity开发之辅助脚本(自动绑定prefab)

作者: gt154 | 来源:发表于2018-08-08 18:41 被阅读196次

    这段时间都没更新,原因很简单,懒癌上身,得治啊...

    正好最近写了个工具,可以选中prefab,自动查找相应脚本并绑定prefab中需引用的组件,本想用在项目里,不过可能用不到了,虽然没太大用,也就省点拖拽的力,但都已经写出来了,想着也不要浪费,于是乎,这篇文章诞生了。

    使用规则

    1. prefab名字应与c#脚本名一致

    2. 脚本中成员变量的命名与prefab中相应的组件相同,且命名不可重复!!!
      脚本中成员变量的命名与prefab中相应的组件相同,且命名不可重复!!!
      脚本中成员变量的命名与prefab中相应的组件相同,且命名不可重复!!!

    重要的事情说三遍,我是以名字为tag的,所以命名为什么重要大家应该明白了。
     


    代码

    1.UIPathData类

    public class UIPathData
    {
        private string name;
    
        public string Name
        {
            get { return name; }
        }
    
    
        string folder;
    
        public string Folder
        {
            get { return folder; }
        }
    
        public UIPathData(string name, string folder)
        {
            this.name = name;
            this.folder = folder;
        }
    }
    

    2.Tools类

    public class Tools {
    
        private static string scriptsPath = Application.dataPath + "/Scripts";
        private static string prefabDirPath = Application.dataPath + "/Prefab";
    
        [MenuItem("Tools/UI/Remove c# file in prefab")]
        public static void removeCSharpFiles()
        {
            string[] paths = Directory.GetFiles(prefabDirPath, "*.prefab", SearchOption.AllDirectories);
            Debug.Log("-------count :  " + paths.Length);
            for (int i = 0; i < paths.Length; ++i)
            {
                string path = paths[i].Replace(@"\", "/");
                path = path.Substring(path.IndexOf("Assets"));
                GameObject obj = AssetDatabase.LoadAssetAtPath(@path, typeof(GameObject)) as GameObject;
                MonoBehaviour mono = obj.GetComponent<MonoBehaviour>();
                if (mono != null)
                {
                    Debug.Log("-------remove mono in  " + obj.name);
                    GameObject.DestroyImmediate(mono, true);
                }
            }
        }
    
        [MenuItem("Assets/Bind C# file to prefabs in Directory")]
        public static void bindScriptToPrefabs()
        {
            string dirname;
            UnityEngine.Object[] objs = Selection.GetFiltered(typeof(UnityEngine.Object), SelectionMode.Unfiltered);
            if (objs.Length > 0)
            {
                dirname = string.Format("{0}/{1}", Path.GetDirectoryName(AssetDatabase.GetAssetPath(objs[0])), objs[0].name);
                string[] paths = Directory.GetFiles(dirname, "*.prefab", SearchOption.AllDirectories);
                for (int i = 0; i < paths.Length; ++i)
                {
                    string path = paths[i].Replace(@"\", "/");
                    bindFileToPrefab(path);
                }
            }
        }
     
    
        [MenuItem("Assets/Bind C# file to prefab")]
        public static void bindScriptToPrefab()
        {
            bindFileToPrefab(null);
        }
        
        public static void bindFileToPrefab(string path)
        {
            if (path == null && Selection.assetGUIDs.Length > 0)
            {
                path = AssetDatabase.GUIDToAssetPath(Selection.assetGUIDs[0]);
            }
    
            string[] paths = Directory.GetFiles(scriptsPath, "*.cs", SearchOption.AllDirectories);
            FileInfo[] files = new FileInfo[paths.Length];
            for (int i = 0; i < paths.Length; ++i)
            {
                files[i] = new FileInfo(paths[i]);
            }
    
            GameObject prefab = AssetDatabase.LoadAssetAtPath<GameObject>(path);
            if (prefab != null)
            {
                MonoBehaviour mono = prefab.GetComponent<MonoBehaviour>();
                if(mono != null)
                {
                    GameObject.DestroyImmediate(mono, true);
                }
    
    
                string name = prefab.name;
                bool tag = false;
                for (int i = 0; i < files.Length; ++i)
                {
                    if (files[i].Name.Split('.')[0].Equals(name))
                    {
                        foreach (var asm in AppDomain.CurrentDomain.GetAssemblies())
                        {
                            Type t = asm.GetType(name);
                            if (t != null)
                            {
                                prefab.AddComponent(t);
                                tag = true;
                                break;
                            }
                        }
    
                        if(tag)
                        {
                            break;
                        }
                    }
                }
    
                mono = prefab.GetComponent<MonoBehaviour>();
                if(mono != null)
                {
                    Type t = mono.GetType();
                    FieldInfo[] fields = t.GetFields();
                    string[] uipaths = UIRelativePath(prefab.gameObject.transform, fields);
                    for (int i = 0; i < fields.Length; ++i)
                    {
                        var component = prefab.gameObject.transform.Find(uipaths[i]).GetComponent(fields[i].FieldType);
                        fields[i].SetValue(mono, component);
                    }
                    Debug.Log("------- bind " + prefab.name + ".prefab success ! ");
                }
            }
        }
    
        private static string[] UIRelativePath(Transform root, FieldInfo[] fields)
        {
            string[] result = new string[fields.Length];
    
            Stack<KeyValuePair<Transform, string>> stack = new Stack<KeyValuePair<Transform, string>>();
            stack.Push(new KeyValuePair<Transform, string>(root, ""));
            while (stack.Count > 0)
            {
                KeyValuePair<Transform, string> node = stack.Pop();
                for (int t = 0; t < fields.Length; ++t)
                {
                    if (node.Key.name.Equals(fields[t].Name))
                    {
                        result[t] = node.Value;
                        break;
                    }
                }
    
                for (int i = 0; i < node.Key.childCount; ++i)
                {
                    Transform child = node.Key.GetChild(i);
                    string path = node.Value.Equals("") ? child.name : string.Format("{0}/{1}", node.Value, child.name);
                    stack.Push(new KeyValuePair<Transform, string>(child, path));
                }
    
            }
    
            return result;
        }
    }
    

    这里面其实还应该做个检查,是否有存在命名相同的情况,按规则是不允许出现命名相同的。
    最后还是欢迎大家给出各种建议和意见,以及附上源码地址
    源码地址:https://github.com/gtgt154/ScriptBindToPrefab

    相关文章

      网友评论

          本文标题:unity开发之辅助脚本(自动绑定prefab)

          本文链接:https://www.haomeiwen.com/subject/ihvxbftx.html