Test123/Assets/RL_DevPlus1/Editor/ProjectAnalyzer/RLSceneAnalyzer.cs
Mohan pal singh ubhi 25012163c2
Some checks failed
Code Documentation / code-docs (push) Has been cancelled
Project Report / project-report (push) Has been cancelled
Validate Code / validate (push) Has been cancelled
Update 2
2026-06-15 22:11:54 +03:00

197 lines
7.1 KiB
C#

using System.Collections.Generic;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;
using UnityEngine.SceneManagement;
namespace RunlevelSystems.DevPlus1.EditorTools
{
public static class RLSceneAnalyzer
{
public static List<RLSceneInfo> AnalyzeOpenScenes()
{
List<RLSceneInfo> results = new List<RLSceneInfo>();
for (int i = 0; i < SceneManager.sceneCount; i++)
{
Scene scene = SceneManager.GetSceneAt(i);
if (scene.IsValid() && scene.isLoaded)
{
results.Add(AnalyzeLoadedScene(scene));
}
}
return results;
}
public static List<RLSceneInfo> AnalyzeBuildSettingsScenes()
{
List<string> paths = new List<string>();
foreach (EditorBuildSettingsScene scene in EditorBuildSettings.scenes)
{
if (scene.enabled)
{
paths.Add(scene.path);
}
}
return AnalyzeScenePaths(paths);
}
public static List<RLSceneInfo> AnalyzeAllAssetScenes()
{
List<string> paths = new List<string>();
foreach (string guid in AssetDatabase.FindAssets("t:Scene"))
{
paths.Add(AssetDatabase.GUIDToAssetPath(guid));
}
return AnalyzeScenePaths(paths);
}
private static List<RLSceneInfo> AnalyzeScenePaths(List<string> paths)
{
List<RLSceneInfo> results = new List<RLSceneInfo>();
if (HasDirtyOpenScenes())
{
RLSceneInfo skipped = new RLSceneInfo();
skipped.sceneName = "Scene analysis skipped";
skipped.scenePath = "Open scenes contain unsaved changes";
skipped.notes = "The analyzer does not save scenes. Save or discard changes manually, then run scene analysis again.";
results.Add(skipped);
return results;
}
SceneSetup[] setup = EditorSceneManager.GetSceneManagerSetup();
try
{
foreach (string path in paths)
{
//ignore scenes in packages since they can't be loaded for analysis
if (path.StartsWith("Packages/")) {
continue;
}
if (string.IsNullOrEmpty(path))
{
continue;
}
Scene scene = EditorSceneManager.OpenScene(path, OpenSceneMode.Single);
results.Add(AnalyzeLoadedScene(scene));
}
}
finally
{
if (setup != null && setup.Length > 0)
{
EditorSceneManager.RestoreSceneManagerSetup(setup);
}
}
return results;
}
private static bool HasDirtyOpenScenes()
{
for (int i = 0; i < SceneManager.sceneCount; i++)
{
Scene scene = SceneManager.GetSceneAt(i);
if (scene.isDirty)
{
return true;
}
}
return false;
}
private static RLSceneInfo AnalyzeLoadedScene(Scene scene)
{
RLSceneInfo info = new RLSceneInfo();
info.scenePath = scene.path;
info.sceneName = scene.name;
info.buildIndex = scene.buildIndex;
GameObject[] roots = scene.GetRootGameObjects();
info.rootGameObjectCount = roots.Length;
foreach (GameObject root in roots)
{
info.rootGameObjects.Add(root.name);
AnalyzeGameObjectRecursive(root, root.name, scene.path, info);
}
return info;
}
public static void AnalyzeGameObjectRecursive(GameObject gameObject, string hierarchyPath, string sourcePath, RLSceneInfo sceneInfo)
{
RLGameObjectInfo goInfo = AnalyzeGameObject(gameObject, hierarchyPath);
sceneInfo.gameObjects.Add(goInfo);
sceneInfo.totalGameObjects++;
if (gameObject.activeSelf) sceneInfo.activeGameObjects++;
else sceneInfo.inactiveGameObjects++;
sceneInfo.missingScriptCount += goInfo.missingScriptCount;
sceneInfo.missingReferenceCount += goInfo.missingReferenceCount;
sceneInfo.unityEvents.AddRange(RLUnityEventAnalyzer.ExtractUnityEvents(gameObject, sourcePath, hierarchyPath));
foreach (Transform child in gameObject.transform)
{
AnalyzeGameObjectRecursive(child.gameObject, hierarchyPath + "/" + child.name, sourcePath, sceneInfo);
}
}
public static RLGameObjectInfo AnalyzeGameObject(GameObject gameObject, string hierarchyPath)
{
RLGameObjectInfo info = new RLGameObjectInfo();
info.hierarchyPath = hierarchyPath;
info.activeSelf = gameObject.activeSelf;
info.tag = gameObject.tag;
info.layer = gameObject.layer;
info.missingScriptCount = GameObjectUtility.GetMonoBehavioursWithMissingScriptCount(gameObject);
Component[] components = gameObject.GetComponents<Component>();
foreach (Component component in components)
{
if (component == null)
{
info.components.Add("Missing Script");
continue;
}
info.components.Add(component.GetType().Name);
MonoBehaviour monoBehaviour = component as MonoBehaviour;
if (monoBehaviour != null)
{
info.attachedScripts.Add(component.GetType().Name);
}
CollectSerializedReferences(component, info);
}
return info;
}
private static void CollectSerializedReferences(Component component, RLGameObjectInfo info)
{
SerializedObject serializedObject = new SerializedObject(component);
SerializedProperty property = serializedObject.GetIterator();
bool enterChildren = true;
while (property.NextVisible(enterChildren))
{
enterChildren = false;
if (property.propertyType != SerializedPropertyType.ObjectReference)
{
continue;
}
if (property.objectReferenceValue != null)
{
string referenceName = property.displayName + " -> " + property.objectReferenceValue.name;
if (!info.referencedObjects.Contains(referenceName))
{
info.referencedObjects.Add(referenceName);
}
}
else if (property.objectReferenceInstanceIDValue != 0)
{
info.missingReferenceCount++;
}
}
}
}
}