2019年3月11日月曜日

【Unity】ビルドするとタグの挙動がおかしくなる現象の対処法(Unityを再起動する)

タグをいじったあとにビルドするとうまく動かない現象があったので記事にしておきます。

現象


Tags&Layersでタグの削除をしてそのままビルド実行するとtransform.tag、FindGameObjectsWithTagメソッド、FindWithTagメソッドの動作がエディタ実行したときと異なる。


再現環境


Unity 2018.3.7f1


再現手順


Tags&Layersで「HogeTag」、「SphereTag」、「CubeTag」を追加する。



Capsule、Sphere、Cube、Cubeをシーンに追加する。それぞれタグを「Player」、「SphereTag」、「CubeTag」、「CubeTag」にする。
それらの子に3D Text(TagText)を追加し、別に3D Text(AllTagText)を追加する。

TagTextには親のタグとインスペクターで設定した文字列をFindWithTagで探した結果をテキストに表示するスクリプト(TagText.cs)をアタッチする。
AllTagsTextにはインスペクターで設定した文字列をFindGameObjectsWithTagで探した結果をテキストに表示するスクリプト(AllTagsText.cs)をアタッチする。
TagText.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
using System;
using UnityEngine;
 
public class TagText : MonoBehaviour
{
    [SerializeField] private string _targetTag;
 
    // Start is called before the first frame update
    void Start()
    {
        TextMesh textMesh = GetComponent<textmesh>();
        GameObject obj;
 
        textMesh.text = "[";
        try
        {
            textMesh.text += transform.parent.tag;
        }
        catch (Exception e)
        {
            textMesh.text += e.Message;
        }
 
        textMesh.text += "]\n";
         
        try
        {
            // タグが存在しない、または空文字やnullを渡した場合はUnityExceptionの例外が発生
            // もし見つからない場合はnullを返す
            obj = GameObject.FindWithTag(_targetTag);
        }
        catch (Exception e)
        {
            textMesh.text += " " + e.Message;
            return;
        }
 
        if (obj != null)
        {
            // FindWithTagでヒットした
            textMesh.text += _targetTag + " exist";
        }
        else
        {
            // FindWithTagでヒットしなかった
            textMesh.text += _targetTag + " doesn't exist";
        }
    }
}
AllTagsText.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
using System;
using UnityEngine;
 
public class AllTagsText : MonoBehaviour
{
    [SerializeField] private string[] _targetTags;
 
    // Start is called before the first frame update
    void Start()
    {
        TextMesh textMesh = GetComponent<textmesh>();
        textMesh.text = "";
             
        foreach (var targetTag in _targetTags)
        {
            GameObject[] objects;
            try
            {
                // タグが存在しない、または空文字やnullを渡した場合はUnityExceptionの例外が発生
                // もし見つからない場合は空配列を返す
                objects = GameObject.FindGameObjectsWithTag(targetTag);
            }
            catch (Exception e)
            {
                textMesh.text += targetTag + ":" + e.Message + "\n";
                continue;
            }
 
            if (objects != null)
            {
                if (objects.Length == 0)
                {
                    // FindGameObjectsWithTagでヒットしなかった
                    textMesh.text += targetTag + ":Nothing\n";
                    continue;
                    ;
                }
 
                foreach (var obj in objects)
                {
                    // FindGameObjectsWithTagでヒットした
                    textMesh.text += targetTag + ":" + obj.name + "\n";
                }
            }
            else
            {
                // 通常ここには到達しない
                textMesh.text += targetTag + ":null\n";
            }
        }
    }
}

この状態でエディタ実行するとそれぞれ正常にテキストが表示される。

また、Build and Runしても正常にテキストが表示される。


ここからが本題。
Tags&LayersでHogeTagを削除してNewTagを追加する。

CubeObject2のタグをNewtagにしてエディタ実行する。
すると、削除前と同じようにそれぞれに設定したタグが表示される。

Build and Runをすると……

なんかおかしい。
SphereObjectのタグがCubeTagに置き換わり、SphereTagが存在しないことになっている。
また、CubeObject1のタグがNewTagに置き換わり、CubeObject2のタグが未定義のタグになっている。
その後Save(Save Scene)、Save Project、再ビルドしても同じ結果になる。

これの解決方法はUnityを再起動するしかない。

素直にUnityを再起動してBuild and Runをすると正常な動作となる。


後記


エディタでは正常な動作をするし再ビルドしても直らない現象なので、結構タイムロスしました。
何かおかしいことがあったら一旦再起動すると良いでしょう。

ではまた。
0 件のコメント:
コメントを投稿