22
2017
05

Unity生成Tag枚举代码

        在unity中,tag是一个好东西,我们可以用tag来区分物体,也可以通过tag来快速地查找物体。但是美中不足的是,tag是一个字符串string。为什么说美中不足呢?

        因为假如我们在一个脚本里面想要有一个Tag字段,都只能定义一个string字段。

using UnityEngine;

public class TagObjFinder : MonoBehaviour
{
    public string Tag;

    public GameObject[] FindGos { get; private set; }

    public void Start()
    {
        FindGos = GameObject.FindGameObjectsWithTag(Tag);
    }
}

       而这样的话,在编辑器中,就非常不方便填写,也非常容易出错。

QQ截图20170522210625

       有一些人会采用CustomEditor的方法,利用TagField可以非常好地使用Tag下拉框。这种通过自定义属性面板的方法其实并不赞成,因为总不可能给每一个需要用到tag的脚本都专门给它写一个CustomEditor。

QQ截图20170522210911

        而第二个原因是在代码中使用了大量表示tag的string,非常不优雅,查找和维护都相当不方便。比如:经常看到GameObject.FindGameObjectsWithTag(“Player”)或者是if(gameObject.tag=="GameController”);这样的代码。

        那么有人也想到办法,就是手动定义,const所有的tag。比如

public const string TagPlayer=”Player”;

public const string TagMainCamera=”MainCamera”;

        确实这是一个方法。通过查找const变量可以找到所有的引用,非常方便。可惜的是,在属性面板中,依然需要手动填写。

        既然const不行的话,是不是可以使用枚举呢?当然可以,而且非常优雅。属性面板中还能选择,非常适合。

public enum EmTag

{

    Untagged,

    Respawn,

    Finish,

    EditorOnly,

    MainCamera,

    Player,

    GameController,

}

我们改写一下TagObjFinder

using UnityEngine;

public class TagObjFinder : MonoBehaviour
{
    public EmTag Tag;

    public GameObject[] FindGos { get; private set; }

    public void Start()
    {
        FindGos = GameObject.FindGameObjectsWithTag(Tag.ToString());
    }
}

QQ截图20170522211801(看起来和TagField的效果是一样的)

        不过有一个麻烦的就是,如果我在unity中增加了一个tag,就需要增加在代码中一个枚举值。这时候,unity的易扩展性就发挥出来了,我们完全可以自动生成这个EmTag枚举的代码。

using System.IO;
using System.Text;
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;

public class TagEnumGenarator : MonoBehaviour
{
    [MenuItem("Tools/GenTagEnum")]
    public static void GenTagEnum()
    {
        var tags = InternalEditorUtility.tags;
        var arg = "";
        foreach (var tag in tags)
        {
            arg += "\t" + tag + ",\n";
        }
        var res = "public enum EmTag\n{\n" + arg + "}\n";
        var path = Application.dataPath + "/Tool/EmTag.cs";
        File.WriteAllText(path, res, Encoding.UTF8);
        AssetDatabase.SaveAssets();
        AssetDatabase.Refresh();
    }
}

        通过InternalEditorUtility.tags获取到unity中已有的所有tag,然后通过File.WriteAllText方法写入到一个cs文件中,这里把这个文件EmTag.cs放在了”Assets/Tool/”下。

        编译完成,ok。这样只要增加tag的时候,点击一下菜单上的Tools->GenTagEnum就可以同步代码了。然后愉快地抛弃string tag,快乐地使用enum tag。

« 上一篇下一篇 »