目录
1.参考资料
2. 代码添加层
2.1创建C#类,生命静态构造方法
2.2判断层是否存在
2.3添加层
3.momo版本修改版
4.完整代码(两个版本)
4.1 InitializeOnLoad版本
4.2 AssetPostprocessor版本
1.参考资料
代码添加层,借鉴于 雨松MOMO的Unity3D研究院之脚本自动添加tag和Layer,他的这个版本是比较早的,现在的版本不完全支持,需要做修改。另外一份参考是Unity 自动添加tag,SortingLayers,Layer
两个是有区别的,雨松的脚本是继承AssetPostprocessor,在调用的静态方法OnPostprocessAllAssets中,去实现添加层,该方法的触发机制如下。
另一份是通过[InitializeOnLoad]实现,需求是C#类要有静态的构造方法,官方文档
2. 代码添加层
2.1创建C#类,生命静态构造方法
在类上添加[InitializeOnLoad],这样就能在加载时调用
using UnityEditor;
using UnityEngine;
[InitializeOnLoad]
public class TagManagerAutoAdd
{
static TagManagerAutoAdd()
{
Add();
}
static void Add()
{
AutoAddLayer("Build");
}
2.2判断层是否存在
通过UnityEditorInternal.InternalEditorUtility.layers数组判断是否存在该层。
static bool HasThisLayer(string layer)
{
for(int i=0;i<UnityEditorInternal.InternalEditorUtility.layers.Length;i++)
{
if(UnityEditorInternal.InternalEditorUtility.layers[i].Contains(layer))
{
return true;
}
}
return false;
}
补充说明:在设置的过程中,尝试过多次添加同一个名称的Layer,结果引起,所有空白的layer层全部被占用。为了应对该种情况,在判断之前,执行清理,清理掉所有的层中指定名称的层。注意:前面8层是unity系统使用的层,所以要先过滤掉,因为下标3 6 7是空的,不过滤,会造成层设置成功,但却设置到unity系统使用的层之中,而不能使用。
static bool HasThisLayer(string layer)
{
//先清除已保存的
SerializedObject tagManager = new SerializedObject(AssetDatabase.LoadAllAssetsAtPath("ProjectSettings/Tagmanager.asset"));
SerializedProperty it = tagManager.GetIterator();
while(it.NextVisible(true))
{
if(it.name.Equals("layers"))
{
for(int i=0;i<it.arraySize;i++)
{
if(i<=7)
{
continue;
}
SerializedProperty sp = it.GetArrayElementAtIndex(i);
if(!string.IsNullOrEmpty(sp.stringValue))
{
if(sp.stringValue.Equals(layer))
{
sp.stringValue = string.Empty;
tagManager.ApplyModifiedProperties();
}
}
}
}
}
for(int i=0;i<UnityEditorInternal.InternalEditorUtility.layers.Length;i++)
{
if(UnityEditorInternal.InternalEditorUtility.layers[i].Contains(layer))
{
return true;
}
}
return false;
}
2.3添加层
如果层存在,则不处理,层不存在,则通过添加。注意:添加层,要过滤掉前面8个层,因为那是unity系统使用的,设置后没有效果。
static TagManagerAutoAdd()
{
Add();
}
[MenuItem("Tools/AddLayer/Build")]
static void Add()
{
AutoAddLayer("Build");
}
static void AutoAddLayer(string layer)
{
if(!HasThisLayer(layer))
{
SerializedObject tagMagager = new SerializedObject(AssetDatabase.LoadAllAssetsAtPath("ProjectSettings/Tagmanager.asset"));
SerializedProperty it = tagMagager.GetIterator();
while(it.NextVisible(true))
{
if(it.name.Equals("layers"))
{
for(int i=0;i<it.arraySize;i++)
{
if(i<=7)
{
continue;
}
SerializedProperty sp = it.GetArrayElementAtIndex(i);
if(string.IsNullOrEmpty(sp.stringValue))
{
sp.stringValue = layer;
tagMagager.ApplyModifiedProperties();
Debug.Log("success");
return;
}
}
}
}
}
}
}
}
补充说明[MenuItem("Tools/AddLayer/Build")],这是扩展UnityEditor的菜单,添加了一个菜单,点击后,调用静态的Add()方法。
3.momo版本修改版
该版本主要问题是it.NextVisible(true)后,没有对it继续展开,导致后面的it.stringvalue无效报错,不建议采用,仅提供参考。
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
public class AutoAddLayer : AssetPostprocessor
{
static void OnPostprocessAllAssets(string[] importedAssets,string[] deletedAssets,string[] movedAssets,string[] movedFromAssetPaths)
{
Debug.Log("post");
foreach(string str in importedAssets)
{
Debug.Log("foreach :" + str);
if(str.EndsWith("AutoAddLayer.cs"))
{
Debug.Log("autoadd");
AddLayer("Build");
return;
}
}
//for(int i=0;i<importedAssets.Length;i++)
//{
// if(importedAssets[i].Equals("Assets/BuildTools/Editor/AutoAddLayer.cs"))
// {
// AddLayer("Build");
// return
// }
//}
}
static void AddLayer(string layerName)
{
if(!HaveLayer(layerName))
{
Debug.Log("no have");
SerializedObject tagManager = new SerializedObject(AssetDatabase.LoadAllAssetsAtPath("ProjectSettings/Tagmanager.asset")[0]);
SerializedProperty it = tagManager.GetIterator();
while(it.NextVisible(true))
{
Debug.Log("while:" + it.name+" type:"+it.type);//部分it的type不是stringvalue,所以会报错 it.stringvalue报错
if(it.name.Equals("layers"))
{
Debug.Log("layers");
if (it.type == "vector")
{
Debug.Log("vector 类型");
if (string.IsNullOrEmpty(it.stringValue.ToString()))
{
Debug.Log("值为空");
it.stringValue = layerName;
tagManager.ApplyModifiedProperties();
Debug.Log("success");
return;
}
}
}
}
}else
{
Debug.Log("have");
}
}
static bool HaveLayer(string layerName)
{
for(int i=0;i<UnityEditorInternal.InternalEditorUtility.layers.Length;i++)
{
if(UnityEditorInternal.InternalEditorUtility.layers[i].Contains(layerName))
{
return true;
}
}
return false;
}
}
4.完整代码(两个版本)
4.1 InitializeOnLoad版本
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
[InitializeOnLoad]
public class TagManagerAutoAdd
{
static TagManagerAutoAdd()
{
Add();
}
[MenuItem("Tools/AddLayer/Build")]
static void Add()
{
AutoAddLayer("Build");
}
static void AutoAddLayer(string layer)
{
if(!HasThisLayer(layer))
{
SerializedObject tagMagager = new SerializedObject(AssetDatabase.LoadAllAssetsAtPath("ProjectSettings/Tagmanager.asset"));
SerializedProperty it = tagMagager.GetIterator();
while(it.NextVisible(true))
{
if(it.name.Equals("layers"))
{
for(int i=0;i<it.arraySize;i++)
{
if(i<=7)
{
continue;
}
SerializedProperty sp = it.GetArrayElementAtIndex(i);
if(string.IsNullOrEmpty(sp.stringValue))
{
sp.stringValue = layer;
tagMagager.ApplyModifiedProperties();
Debug.Log("success");
return;
}
}
}
}
}
}
static bool HasThisLayer(string layer)
{
//先清除已保存的
SerializedObject tagManager = new SerializedObject(AssetDatabase.LoadAllAssetsAtPath("ProjectSettings/Tagmanager.asset"));
SerializedProperty it = tagManager.GetIterator();
while(it.NextVisible(true))
{
if(it.name.Equals("layers"))
{
for(int i=0;i<it.arraySize;i++)
{
if(i<=7)
{
continue;
}
SerializedProperty sp = it.GetArrayElementAtIndex(i);
if(!string.IsNullOrEmpty(sp.stringValue))
{
if(sp.stringValue.Equals(layer))
{
sp.stringValue = string.Empty;
tagManager.ApplyModifiedProperties();
}
}
}
}
}
for(int i=0;i<UnityEditorInternal.InternalEditorUtility.layers.Length;i++)
{
if(UnityEditorInternal.InternalEditorUtility.layers[i].Contains(layer))
{
return true;
}
}
return false;
}
}
4.2 AssetPostprocessor版本
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
public class AutoAddLayer : AssetPostprocessor
{
static void OnPostprocessAllAssets(string[] importedAssets,string[] deletedAssets,string[] movedAssets,string[] movedFromAssetPaths)
{
// Debug.Log("post");
foreach(string str in importedAssets)
{
// Debug.Log("foreach:"+str);
if(str.EndsWith("AutoAddLayer.cs"))
{
//.Log("auto");
AddLayer00("Build");
return;
}
}
}
static void AddLayer00(string layer)
{
if(!HasLay(layer))
{
//Debug.Log("no have");
SerializedObject tagManager = new SerializedObject(AssetDatabase.LoadAllAssetsAtPath("ProjectSettings/Tagmanager.asset"));
SerializedProperty it = tagManager.GetIterator();
while(it.NextVisible(true))
{
//Debug.Log("while:" + it.name);
if(it.name.Equals("layers"))
{
for(int i=0; i<it.arraySize;i++)
{
if(i<=7)
{
continue;
}
SerializedProperty sp = it.GetArrayElementAtIndex(i);
if(string.IsNullOrEmpty(sp.stringValue))
{
sp.stringValue = layer;
tagManager.ApplyModifiedProperties();
//Debug.Log("i:"+i+" str:"+sp.stringValue);
Debug.Log("success");
return;
}else
{
//Debug.Log("i:"+i+" stringvalue:" + sp.stringValue);
}
}
}
}
}else
{
//Debug.Log("have");
}
}
static bool HasLay(string lay)
{
//防止原先已经设置过了之后,后面没办法修改,所以这边先遍历一遍,并清除数据
SerializedObject tagManager = new SerializedObject(AssetDatabase.LoadAllAssetsAtPath("ProjectSettings/Tagmanager.asset"));
SerializedProperty it = tagManager.GetIterator();
while(it.NextVisible(true))
{
if(it.name.Equals("layers"))
{
for(int i=0;i<it.arraySize;i++)
{
SerializedProperty sp = it.GetArrayElementAtIndex(i);
if(!string.IsNullOrEmpty(sp.stringValue))
{
if(sp.stringValue.Equals(lay))
{
sp.stringValue = string.Empty;
// Debug.Log("设置为空");
tagManager.ApplyModifiedProperties();
}
}
}
}
}
for(int i=0;i<UnityEditorInternal.InternalEditorUtility.layers.Length;i++)
{
if(UnityEditorInternal.InternalEditorUtility.layers[i].Contains(lay))
{
return true;
}
}
return false;
}
}