Skip to content

Instantly share code, notes, and snippets.

@danilodelponte
Created February 3, 2023 22:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save danilodelponte/f0fc8a679a62b7caa854b9735f893b4b to your computer and use it in GitHub Desktop.
Save danilodelponte/f0fc8a679a62b7caa854b9735f893b4b to your computer and use it in GitHub Desktop.
LayerChangerEditor
using System.IO;
using UnityEditor;
using UnityEngine;
public class LayerChangerEditor : EditorWindow
{
private int fromLayerIndex = 0;
private int toLayerIndex = 0;
private string[] layerNames;
private bool changeSceneObjects = false;
private bool changePrefabs = false;
private bool changeChildObjects = false;
private static readonly string logFilePath = "/../Logs/layer_change_log.txt";
[MenuItem("Tools/Layer Changer")]
public static void ShowWindow()
{
GetWindow<LayerChangerEditor>("Layer Changer");
if (!File.Exists(logFilePath)) File.WriteAllText(Application.dataPath + logFilePath, "");
}
private void OnGUI()
{
GUILayout.BeginVertical();
GUILayout.Label("Change Layer", EditorStyles.boldLabel);
GUILayout.EndVertical();
GUILayout.Space(20);
layerNames = GetLayerNames();
fromLayerIndex = EditorGUILayout.Popup("From Layer", fromLayerIndex, layerNames);
toLayerIndex = EditorGUILayout.Popup("To Layer", toLayerIndex, layerNames);
GUILayout.Space(20);
changeSceneObjects = EditorGUILayout.Toggle("Change Scene Objects", changeSceneObjects);
changePrefabs = EditorGUILayout.Toggle("Change Prefabs", changePrefabs);
changeChildObjects = EditorGUILayout.Toggle("Change Child Objects", changeChildObjects);
GUILayout.Space(20);
if (GUILayout.Button("Change Layers"))
{
Log("\n----------------- Changing Layers -----------------");
if (changePrefabs)
ChangeAssets();
if (changeSceneObjects)
ChangeSceneObjects();
Log("----------------- Done -----------------\n");
}
}
private void ChangeSceneObjects()
{
string fromLayer = layerNames[fromLayerIndex];
string toLayer = layerNames[toLayerIndex];
GameObject[] allSceneObjects = UnityEngine.SceneManagement.SceneManager.GetActiveScene().GetRootGameObjects();
foreach (GameObject obj in allSceneObjects)
{
if (obj.layer == LayerMask.NameToLayer(fromLayer))
{
obj.layer = LayerMask.NameToLayer(toLayer);
Log("SceneObject " + obj + " Updated From " + fromLayer + "To Layer " + toLayer + ".", obj);
}
}
}
private string[] GetLayerNames()
{
int numLayers = 32;
string[] layerNames = new string[numLayers];
for (int i = 0; i < numLayers; i++)
{
layerNames[i] = LayerMask.LayerToName(i);
}
return layerNames;
}
private bool ChangeChildLayers(GameObject obj, string fromLayer, string toLayer)
{
int fromLayerIndex = LayerMask.NameToLayer(fromLayer);
int toLayerIndex = LayerMask.NameToLayer(toLayer);
bool changed = false;
foreach (Transform child in obj.transform)
{
var childObj = child.gameObject;
if (childObj.layer == fromLayerIndex)
{
if (HasMissingScripts(childObj))
{
string msg = "Child " + childObj.name + " from prefab ";
Transform parent = obj.transform;
string parentName = parent.gameObject.name;
parent = parent.parent;
while (parent != null)
{
parentName = parent.gameObject.name + "/" + parentName;
parent = parent.parent;
}
msg += parentName + " contains missing scripts. Skipping.";
Log(msg);
return false;
}
childObj.layer = toLayerIndex;
changed = true;
}
changed = ChangeChildLayers(child.gameObject, fromLayer, toLayer) || changed;
}
return changed;
}
private void ChangeAssets()
{
string fromLayer = layerNames[fromLayerIndex];
string toLayer = layerNames[toLayerIndex];
string[] allAssetGuids = AssetDatabase.FindAssets("t:GameObject");
foreach (string assetGuid in allAssetGuids)
{
string assetPath = AssetDatabase.GUIDToAssetPath(assetGuid);
GameObject asset = AssetDatabase.LoadAssetAtPath<GameObject>(assetPath);
bool layerChanged = false;
GameObject instance = (GameObject)PrefabUtility.InstantiatePrefab(asset);
if (instance.layer == LayerMask.NameToLayer(fromLayer))
{
if (HasMissingScripts(instance))
{
Log("Prefab " + instance.name + " contains missing scripts. Skipping.");
GameObject.DestroyImmediate(instance);
continue;
}
instance.layer = LayerMask.NameToLayer(toLayer);
layerChanged = true;
}
if (changeChildObjects && ChangeChildLayers(instance, fromLayer, toLayer)) layerChanged = true;
if (layerChanged)
{
PrefabUtility.ApplyPrefabInstance(instance, InteractionMode.AutomatedAction);
Log("Prefab " + instance + " at " + assetPath + " Updated From " + fromLayer + "To Layer " + toLayer + ".", instance);
}
GameObject.DestroyImmediate(instance);
}
}
private bool HasMissingScripts(GameObject obj)
{
MonoBehaviour[] components = obj.GetComponents<MonoBehaviour>();
foreach (MonoBehaviour component in components)
{
if (!component)
{
return true;
}
}
Transform[] transforms = obj.GetComponentsInChildren<Transform>(true);
foreach (Transform transform in transforms)
{
GameObject childPrefab = (GameObject)PrefabUtility.GetCorrespondingObjectFromSource(transform.gameObject);
if (childPrefab == null)
{
return false;
}
}
return false;
}
public void Log(string message, Object context = null)
{
Debug.Log(message, context);
File.AppendAllText(Application.dataPath + logFilePath, message + System.Environment.NewLine);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment