From 3802ca557c56ddc776bcb03e652fc132f7ca9fd6 Mon Sep 17 00:00:00 2001 From: Anders Ejlersen Date: Wed, 27 May 2026 19:17:55 +0200 Subject: [PATCH 1/3] Validator: Duplicate component validator is now only run on types without DisallowMultipleComponent attribute --- .../GameObjectValidatorDuplicateComponents.cs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/Editor/Validators/GameObject/GameObjectValidatorDuplicateComponents.cs b/Editor/Validators/GameObject/GameObjectValidatorDuplicateComponents.cs index 1ea0509..eaf89a1 100644 --- a/Editor/Validators/GameObject/GameObjectValidatorDuplicateComponents.cs +++ b/Editor/Validators/GameObject/GameObjectValidatorDuplicateComponents.cs @@ -1,4 +1,6 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; +using System.Reflection; using UnityEngine; using UnityEngine.Pool; @@ -28,7 +30,7 @@ namespace Module.ProjectValidator.Editor } else { - if (count > 1) + if (count > 1 && IsMultipleComponentsAllowed(type)) results.Add(ValidatorResult.Create(EValidatorSeverity.Warning, $"GameObject has duplicate '{type.Name}' ({count}) components")); type = t; @@ -36,8 +38,13 @@ namespace Module.ProjectValidator.Editor } } - if (count > 1) + if (count > 1 && IsMultipleComponentsAllowed(type)) results.Add(ValidatorResult.Create(EValidatorSeverity.Warning, $"GameObject has duplicate '{type.Name}' ({count}) components")); } + + private static bool IsMultipleComponentsAllowed(Type type) + { + return type.GetCustomAttribute(true) == null; + } } } \ No newline at end of file From 9dd45f536e3e1715833d5f3cf416f3a81acf557a Mon Sep 17 00:00:00 2001 From: Anders Ejlersen Date: Wed, 27 May 2026 19:24:07 +0200 Subject: [PATCH 2/3] Validator: Fixed issue, where scene wouldn't unload, if an exception is thrown --- Editor/ValidatorRunner.cs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/Editor/ValidatorRunner.cs b/Editor/ValidatorRunner.cs index 5314e60..c99415c 100644 --- a/Editor/ValidatorRunner.cs +++ b/Editor/ValidatorRunner.cs @@ -179,12 +179,12 @@ namespace Module.ProjectValidator.Editor for (var i = 0; i < assets.Length; i++) { + var assetPath = AssetDatabase.GetAssetPath(assets[i]); + var scene = SceneManager.GetSceneByPath(assetPath); + var isLoaded = scene.isLoaded; + try { - var assetPath = AssetDatabase.GetAssetPath(assets[i]); - var scene = SceneManager.GetSceneByPath(assetPath); - var isLoaded = scene.isLoaded; - if (!isLoaded) scene = EditorSceneManager.OpenScene(assetPath, OpenSceneMode.Additive); @@ -194,14 +194,16 @@ namespace Module.ProjectValidator.Editor { ValidateGameObject(rootObjects[j], string.Empty, report, true); } - - if (!isLoaded) - EditorSceneManager.CloseScene(scene, true); } catch (Exception e) { Debug.LogException(e); } + finally + { + if (!isLoaded && scene.isLoaded) + EditorSceneManager.CloseScene(scene, true); + } } } From eb46c22ffc8380fb2c03b69c3d958747ef0e06dd Mon Sep 17 00:00:00 2001 From: Anders Ejlersen Date: Wed, 27 May 2026 21:50:04 +0200 Subject: [PATCH 3/3] Validator: Skipping render pipeline check on shader, fi no RenderPipeline tag is found Validator: Skipping textures in material, if marked as PerRendererData, HideInInspector or NonModifiableTextureData Validator: Fixed issue, where arrays weren't iterated correctly, which resulted in an exception Window: Added warning and error count --- Editor/ValidatorRunner.cs | 14 ++++++- .../Assets/AssetValidatorMaterialShader.cs | 6 ++- .../Assets/AssetValidatorMaterialTexture.cs | 5 ++- Editor/Window/EditorProjectValidatorWindow.cs | 40 +++++++++++++++++-- ...StyleSheetEditorProjectValidatorWindow.uss | 26 +++++++++++- .../UxmlEditorProjectValidatorWindow.uxml | 12 +++++- package.json | 2 +- 7 files changed, 93 insertions(+), 12 deletions(-) diff --git a/Editor/ValidatorRunner.cs b/Editor/ValidatorRunner.cs index c99415c..b69797a 100644 --- a/Editor/ValidatorRunner.cs +++ b/Editor/ValidatorRunner.cs @@ -423,8 +423,18 @@ namespace Module.ProjectValidator.Editor var fieldPath = parentFieldPath; ProjectValidatorUtility.AppendToFieldPath(e.FieldInfo, ref fieldPath); - - if (value is IEnumerable ie) + + if (value is Array arr) + { + for (var j = 0; j < arr.Length; j++) + { + var eObj = arr.GetValue(j); + var fieldPathArrElement = fieldPath; + ProjectValidatorUtility.AppendToFieldPath(j, ref fieldPathArrElement); + Validate(assetGuid, relativePath, fieldPathArrElement, eObj, e.Entry, report); + } + } + else if (value is IEnumerable ie) { var idx = 0; diff --git a/Editor/Validators/Assets/AssetValidatorMaterialShader.cs b/Editor/Validators/Assets/AssetValidatorMaterialShader.cs index 6a0dfce..f6e072f 100644 --- a/Editor/Validators/Assets/AssetValidatorMaterialShader.cs +++ b/Editor/Validators/Assets/AssetValidatorMaterialShader.cs @@ -28,16 +28,20 @@ namespace Module.ProjectValidator.Editor var tagSearch = new ShaderTagId("RenderPipeline"); var tagPipeline = new ShaderTagId(pipeline.renderPipelineShaderTag); + var hasKeyword = false; for (var i = 0; i < shader.passCount; i++) { var tagPass = shader.FindPassTagValue(i, tagSearch); + if (tagPass != ShaderTagId.none) + hasKeyword = true; + if (tagPass == tagPipeline) return true; } - return false; + return !hasKeyword; } } } \ No newline at end of file diff --git a/Editor/Validators/Assets/AssetValidatorMaterialTexture.cs b/Editor/Validators/Assets/AssetValidatorMaterialTexture.cs index 9f07b96..37097fa 100644 --- a/Editor/Validators/Assets/AssetValidatorMaterialTexture.cs +++ b/Editor/Validators/Assets/AssetValidatorMaterialTexture.cs @@ -16,10 +16,13 @@ namespace Module.ProjectValidator.Editor for (var i = 0; i < count; i++) { var propertyType = obj.shader.GetPropertyType(i); + var propertyFlags = obj.shader.GetPropertyFlags(i); if (propertyType != ShaderPropertyType.Texture) continue; - + if ((propertyFlags & (ShaderPropertyFlags.PerRendererData | ShaderPropertyFlags.HideInInspector | ShaderPropertyFlags.NonModifiableTextureData)) != 0) + continue; + var propertyName = obj.shader.GetPropertyName(i); var propertyValue = obj.GetTexture(propertyName); diff --git a/Editor/Window/EditorProjectValidatorWindow.cs b/Editor/Window/EditorProjectValidatorWindow.cs index 7966bc8..1d01017 100644 --- a/Editor/Window/EditorProjectValidatorWindow.cs +++ b/Editor/Window/EditorProjectValidatorWindow.cs @@ -8,12 +8,18 @@ namespace Module.ProjectValidator.Editor { internal sealed class EditorProjectValidatorWindow : EditorWindow { + private VisualElement _groupWarnings; + private Label _labelWarnings; + + private VisualElement _groupErrors; + private Label _labelErrors; + private MultiColumnTreeView _treeView; private string _searchFilter; - + private readonly List> _list = new(); private readonly List> _filteredList = new(); - + public void CreateGUI() { var root = rootVisualElement; @@ -21,6 +27,15 @@ namespace Module.ProjectValidator.Editor root.styleSheets.Add(EditorAssetUtility.LoadFirstAsset("StyleSheetEditorProjectValidatorWindow")); root.Add(asset.Instantiate()); + _groupWarnings = root.Q("status-warnings"); + _labelWarnings = _groupWarnings.Q