Unity通过代码添加层Layer

目录

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;
    }
	
}

 

  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值