【Unity】タグの階層表示と判定方法について

というわけで、今回はUnityのタグに関するお話です!

shot2ss20151124230737479

GameObjectのFindや判定系の処理に大活躍のタグですが、量が多いと管理が面倒であったり、複数のタグを付けれなかったりします。
特に似たような特徴のタグを複数用意する際は雑多になってしまいます。

例えば「ステージ上のオブジェクト」というタグを考えた場合、その種類として
 →「破壊可能なオブジェクト」
 →「破壊不可能なオブジェクト」
 →「持って投げることが可能なオブジェクト」
 →「ブロックオブジェクト」
等が考えられます。

これらを普通に追加するとタグ設定時の選択肢が増えて見にくくなります。
また、グループ分けしての判別もできないので「ブロックオブジェクト」を「ステージ上のオブジェクト」として判定したい場合に面倒なことになります。
今回はそのあたりをいい具合になるよう考えてみました!

タグの階層表示

タグの名前に/(スラッシュ)を入れると、タグが階層構造で表示されるようになります。
メニューのEdit→ProjectSettings→Tag and Layersでタグ一覧を表示し、スラッシュ込みで入力します。

shot2ss20151124230814769

これはタグに限らず、レイヤーやシェーダーなども同様です。
自分はカスタマイズしたシェーダーを「Custom/(シェーダー名)」という名前にし、階層構造にしています。

数が多くなってくると選択するのが大変なので、分けておくと便利です。
冒頭のタグも「StageObject/(タグ名)」といった感じで整理できます。

タグ名の判定

スラッシュを入れると階層構造に出来ますが、参照の仕方は変わりません。
つまり、タグを指定する場合「StageObject/Block」といった形になります。
やや冗長な上、「親タグや子タグを参照」といったことも出来ません。

ただ階層は必ずスラッシュで区切っているので、その前後でタグを見分けることができます。
ということで、親タグ名や子タグ名を取得するUtilityクラスを作ってみました!

using UnityEngine;
using System.Collections;

public static class TagUtility {

    public static string getParentTagName(string name) {
        int pos = name.IndexOf("/");

        if (0 < pos) {
            return name.Substring(0, pos);
        } else {
            return name;
        }
    }

    public static string getParentTagName(GameObject gameObject) {
        string name = gameObject.tag;
        int pos = name.IndexOf("/");

        if (0 < pos) {
            return name.Substring(0, pos);
        } else {
            return name;
        }
    }

    public static string getChildTagName(string name) {
        int pos = name.IndexOf("/");

        if (0 < pos) {
            return name.Substring(pos + 1);
        } else {
            return name;
        }
    }

    public static string getChildTagName(GameObject gameObject) {
        string name = gameObject.tag;
        int pos = name.IndexOf("/");

        if (0 < pos) {
            return name.Substring(pos + 1);
        } else {
            return name;
        }
    }
}

実際にOnTriggerEnter等で使う場合は以下のような感じ。
TagUtilityクラスの関数を呼ぶだけ!

 
public void OnTriggerEnter(Collider c){
    if (TagUtility.getParentTagName(c.gameObject) == "StageObject") {
        // 処理
    }

    if (TagUtility.getChildTagName(c.gameObject) == "Block") {
        // 処理
    }
}

getParentTagName()で親タグ名、getChildTagName()で子タグを取得します。
指定文字列が見つからない場合(=階層構造になっていない)場合はタグ名をそのまま返却します。
文字列での指定の他、GameObjectを渡すことでも取得できるようにしました。

「StageObject/Block」の場合、「StageObject」と「Block」の2パターンで判定できることになります。
Unityは1オブジェクト1タグですが、これで親タグを使ったグループ分けができます。
擬似的ですが、複数のタグを扱っているような感じですね。

これで「ステージオブジェクト」で「ブロックオブジェクト」なものを判別できるようになりました!
他にも敵キャラクターやアイテムを判別する際にも重宝しそうです。
なかなか便利なので、今後も使っていきたいと思います!

余談

シルリスのモデリングを修正し、靴を履いているような感じにしてみました!
他2キャラと比べると適当な足だったので気になっていたところです。
パッと見では短い長靴を履いているようにしか見えませんが、とりあえずこれで十分です。

shot2ss20151124230652229