描述
Unity中设置Tag和Layer的方法,大家都知道,步骤较为繁琐。有时将一些代码复用到其他项目时,经常会出现Tag或Layer,不存在或找不到的情况。我便找到了这几个通过代码添加Tag和Layer的方法。
一种是通过SerializedObject类序列化物体,来设置Tag和Layer;另一种是通过InternalEditorUtility类直接设置Tag。
代码
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;
/// <summary>
/// 添加设置Tag或Layer
/// </summary>
public class AddTagOrLayer
{
/// <summary>
/// 添加或者创建新的标签
/// </summary>
/// <param name="tag">标签名</param>
/// <param name="obj">需要添加的对象</param>
public static void AddOrCreateMyNewTag(string tag, GameObject obj)
{
if (isHasTag(tag))
{
obj.tag = tag;
}
else
{
SerializedObject tagManager = new SerializedObject(obj);//序列化物体
SerializedProperty it = tagManager.GetIterator();//序列化属性
while (it.NextVisible(true))//下一属性的可见性
{
if (it.name == "m_TagString")
{
//Debug.Log(it.stringValue);
it.stringValue = tag;
tagManager.ApplyModifiedProperties();
}
}
}
}
/// <summary>
/// 添加或者创建新的标签
/// </summary>
/// <param name="tag">标签名</param>
/// <param name="obj">需要添加的对象</param>
public static void AddOrCreateNewTag(string tag, GameObject obj)
{
if (!isHasTag(tag))
{
InternalEditorUtility.AddTag(tag);
}
obj.tag = tag;
}
/// <summary>
/// 是否有标签
/// </summary>
/// <param name="tag">标签名</param>
/// <returns>判断结果</returns>
public static bool isHasTag(string tag)
{
string[] tags = InternalEditorUtility.tags;
for (int i = 0; i < tags.Length; i++)
{
if (tags[i].Equals(tag))
return true;
}
return false;
}
/// <summary>
/// 添加或者创建新的层标记
/// </summary>
/// <param name="layer">标记层名</param>
/// <param name="obj">需要添加的对象</param>
public static void AddOrCreateMyNewLayer(string layer, GameObject obj)
{
if (!isHasLayer(layer))
{
SerializedObject tagManager = new SerializedObject(AssetDatabase.LoadAllAssetsAtPath("ProjectSettings/Tagmanager.asset"));
SerializedProperty it = tagManager.GetIterator();
while (it.NextVisible(true))
{
if (it.name == "layers")
{
for (int i = 8; i < it.arraySize; i++)
{
SerializedProperty sp = it.GetArrayElementAtIndex(i);
if (string.IsNullOrEmpty(sp.stringValue))
{
sp.stringValue = layer;
tagManager.ApplyModifiedProperties();
//Debug.Log("success");
break;
}
}
break;
}
}
}
obj.layer = LayerMask.NameToLayer(layer);
}
/// <summary>
/// 是否有层标记
/// </summary>
/// <param name="layer">标记层名</param>
/// <returns>判断结果</returns>
public static bool isHasLayer(string layer)
{
string[] layers = InternalEditorUtility.layers;
for (int i = 0; i < layers.Length; i++)
{
if (layers[i].Contains(layer))
return true;
}
return false;
}
}
注意
该脚本由于引用了UnityEditor和UnityEditorInternal命名空间内的类,需要放在Editor文件夹下,项目才能正常打包。也因此该类也必须由在Editor文件夹下的脚本引用,例如CustomEditor的脚本编辑器脚本。
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
// 自定义编辑器脚本
[CustomEditor(typeof(Part)), CanEditMultipleObjects]
// 这意思就是此脚本为Part脚本的编辑器脚本,CanEditorMutipleObjects 顾名思义,可以同时编辑多个物体
public class PartEditor : Editor
{
protected SerializedProperty scriptProp;
private Part m_Part;
private void OnEnable()
{
scriptProp = serializedObject.FindProperty("m_Script");
m_Part = ((Part)target);
AddTagOrLayer.AddOrCreateMyNewTag("test", m_Part.gameObject);
}
private void Awake()
{
}
public override void OnInspectorGUI()
{
//base.OnInspectorGUI();
serializedObject.Update();
serializedObject.ApplyModifiedProperties();
}
public override bool HasPreviewGUI()
{
return base.HasPreviewGUI();
}
void OnSceneGUI()
{
}
}