Created
February 3, 2023 22:08
-
-
Save danilodelponte/f0fc8a679a62b7caa854b9735f893b4b to your computer and use it in GitHub Desktop.
LayerChangerEditor
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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