#概要
本記事はUnity #2 Advent Calendar 2019 の16日目の記事です。
今回UnityのTag and Layersをスクリプトから設定する方法を書きます。
#前提
Tag and Layersをスクリプトから設定したいケースがあります。
それは、例えば自作ライブラリを提供するときにそのライブラリが特定のレイヤーを利用していて、そのレイヤーをライブラリを使うプロジェクトに追加で上書きしたい場合です。
え、それってProjectSettings/TagManager.assetを渡せばいいんじゃない?ってなるかもしれませんが、TagManager.assetだとレイヤー情報が上書きされてしまうし、その他のtagやSortingLayerの情報も上書きされてしまうので、レイヤーのみを追加したい場合とかだとスクリプトから設定したくなります。
#TagManagerをロードして上書きする
下記ソースでtagManagerの情報をロードします。
var tagManager = new SerializedObject(AssetDatabase.LoadAllAssetsAtPath("ProjectSettings/TagManager.asset")[0]);
そして、下記のように上書き設定したいレイヤーのレイヤー名と番号を定義したのちに上書きます。
//設定したいレイヤーのレイヤー名
private static string[] requiredLayers =
{
"Layer1",
"Layer2",
};
//設定したいレイヤーのレイヤー番号
private static int[] requiredLayerIds =
{
26,
27,
};
/// <summary>
/// 設定したいレイヤーを上書きする
/// </summary>
/// <param name="tagManager"></param>
private static void CheckLayers(SerializedObject tagManager)
{
//layer情報を取得
var layersProp = tagManager.FindProperty("layers");
var index = 0;
foreach (var layerId in requiredLayerIds)
{
if (layersProp.arraySize > layerId)
{
//レイヤーIDのレイヤーを取得
var sp = layersProp.GetArrayElementAtIndex(layerId);
if (sp != null && sp.stringValue != requiredLayers[index])
{
//レイヤー上書き
sp.stringValue = requiredLayers[index];
Debug.Log("Adding layer " + requiredLayers[index]);
}
}
index++;
}
}
最後に、上書きした情報を反映します。
tagManager.ApplyModifiedProperties();
ついでにPhysicsのLayerCollisionMatrixも設定する
下記コマンドでPhysicsのLayerCollisionMatrixの衝突を無視する設定が出来ます。
後はそれぞれ衝突を無視したいレイヤーの組み合わせを網羅すればOK。
var ignoreLayer1 = LayerMask.NameToLayer("Layer1");
var ignoreLayer2 = LayerMask.NameToLayer("Layer2");
Physics2D.IgnoreLayerCollision(ignoreLayer1, ignoreLayer2, true);
Physics.IgnoreLayerCollision(ignoreLayer1, ignoreLayer2, true);
まとめ
以上のコマンドを[MenuItem]で設定してUnityのツールバー等から実行できるようにして、
渡したライブラリを導入した後に設定させれるようにすると完了。
/// <summary>
/// レイヤーを設定する
/// </summary>
[MenuItem("Init/InitLayer")]
static void InitializeLayers()
{
SerializedObject tagManager =
new SerializedObject(AssetDatabase.LoadAllAssetsAtPath(
"ProjectSettings/TagManager.asset")[0]);
CheckLayers(tagManager);
//変更を反映する
tagManager.ApplyModifiedProperties();
//LayerCollisionMatrixもついでに設定する
var ignoreLayer1 = LayerMask.NameToLayer("Layer1");
var ignoreLayer2 = LayerMask.NameToLayer("Layer2");
Physics2D.IgnoreLayerCollision(ignoreLayer1, ignoreLayer2, true);
Physics.IgnoreLayerCollision(ignoreLayer1, ignoreLayer2, true);
}