unity开发之辅助脚本(自动绑定prefab)
2018-08-08 本文已影响196人
gt154
这段时间都没更新,原因很简单,懒癌上身,得治啊...
正好最近写了个工具,可以选中prefab,自动查找相应脚本并绑定prefab中需引用的组件,本想用在项目里,不过可能用不到了,虽然没太大用,也就省点拖拽的力,但都已经写出来了,想着也不要浪费,于是乎,这篇文章诞生了。
使用规则
-
prefab名字应与c#脚本名一致
-
脚本中成员变量的命名与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