Added GameObject Validators
This commit is contained in:
parent
c8a6815316
commit
269789b36f
15 changed files with 160 additions and 13 deletions
|
|
@ -10,6 +10,7 @@ namespace Module.ProjectValidator.Editor
|
||||||
{
|
{
|
||||||
private readonly Dictionary<Type, object> _attributeValidators = new();
|
private readonly Dictionary<Type, object> _attributeValidators = new();
|
||||||
private readonly Dictionary<Type, List<object>> _componentValidators = new();
|
private readonly Dictionary<Type, List<object>> _componentValidators = new();
|
||||||
|
public readonly List<IGameObjectValidator> GameObjectValidators = new();
|
||||||
|
|
||||||
public void AddAttribute(Type type)
|
public void AddAttribute(Type type)
|
||||||
{
|
{
|
||||||
|
|
@ -59,6 +60,22 @@ namespace Module.ProjectValidator.Editor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void AddGameObject(Type type)
|
||||||
|
{
|
||||||
|
if (type.IsInterface || type.IsAbstract)
|
||||||
|
return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var instance = (IGameObjectValidator)FormatterServices.GetUninitializedObject(type);
|
||||||
|
GameObjectValidators.Add(instance);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Debug.LogException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public bool TryGetAttributeValidator(Type type, out object validatorInstance)
|
public bool TryGetAttributeValidator(Type type, out object validatorInstance)
|
||||||
{
|
{
|
||||||
return _attributeValidators.TryGetValue(type, out validatorInstance);
|
return _attributeValidators.TryGetValue(type, out validatorInstance);
|
||||||
|
|
|
||||||
|
|
@ -38,10 +38,10 @@ namespace Module.ProjectValidator.Editor
|
||||||
return window;
|
return window;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static string GetAttributeShortName(Attribute attribute)
|
internal static string GetGameObjectValidatorName(IGameObjectValidator validator)
|
||||||
{
|
{
|
||||||
var str = attribute.GetType().Name;
|
var str = validator.GetType().Name;
|
||||||
str = str.Replace("Attribute", string.Empty);
|
str = str.Replace("GameObjectValidator", string.Empty);
|
||||||
str = ObjectNames.NicifyVariableName(str);
|
str = ObjectNames.NicifyVariableName(str);
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
@ -54,6 +54,14 @@ namespace Module.ProjectValidator.Editor
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static string GetAttributeShortName(Attribute attribute)
|
||||||
|
{
|
||||||
|
var str = attribute.GetType().Name;
|
||||||
|
str = str.Replace("Attribute", string.Empty);
|
||||||
|
str = ObjectNames.NicifyVariableName(str);
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
internal static void AppendToScenePath(GameObject gameObject, ref string scenePath)
|
internal static void AppendToScenePath(GameObject gameObject, ref string scenePath)
|
||||||
{
|
{
|
||||||
scenePath = string.IsNullOrEmpty(scenePath) ? gameObject.name : $"{scenePath}/{gameObject.name}";
|
scenePath = string.IsNullOrEmpty(scenePath) ? gameObject.name : $"{scenePath}/{gameObject.name}";
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ namespace Module.ProjectValidator.Editor
|
||||||
ProjectValidatorUtility.OpenWindow();
|
ProjectValidatorUtility.OpenWindow();
|
||||||
|
|
||||||
stopwatch.Stop();
|
stopwatch.Stop();
|
||||||
Debug.Log(stopwatch.Elapsed.TotalMilliseconds + "ms");
|
Debug.Log($"Validator took {stopwatch.Elapsed.TotalMilliseconds}ms");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -64,8 +64,9 @@ namespace Module.ProjectValidator.Editor
|
||||||
_validatorList = new ValidatorList();
|
_validatorList = new ValidatorList();
|
||||||
_typeTree = new TypeTree();
|
_typeTree = new TypeTree();
|
||||||
|
|
||||||
FetchAllAttributeValidators();
|
FetchAllGameObjectValidators();
|
||||||
FetchAllComponentValidators();
|
FetchAllComponentValidators();
|
||||||
|
FetchAllAttributeValidators();
|
||||||
FetchAllTypesWithValidators<Component>(assemblies);
|
FetchAllTypesWithValidators<Component>(assemblies);
|
||||||
FetchAllTypesWithValidators<ScriptableObject>(assemblies);
|
FetchAllTypesWithValidators<ScriptableObject>(assemblies);
|
||||||
_initialized = true;
|
_initialized = true;
|
||||||
|
|
@ -101,6 +102,16 @@ namespace Module.ProjectValidator.Editor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void FetchAllGameObjectValidators()
|
||||||
|
{
|
||||||
|
var types = TypeCache.GetTypesDerivedFrom(typeof(IGameObjectValidator));
|
||||||
|
|
||||||
|
for (var i = 0; i < types.Count; i++)
|
||||||
|
{
|
||||||
|
_validatorList.AddGameObject(types[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void FetchAllComponentValidators()
|
private static void FetchAllComponentValidators()
|
||||||
{
|
{
|
||||||
var types = TypeCache.GetTypesDerivedFrom(typeof(IComponentValidator<>));
|
var types = TypeCache.GetTypesDerivedFrom(typeof(IComponentValidator<>));
|
||||||
|
|
@ -188,19 +199,39 @@ namespace Module.ProjectValidator.Editor
|
||||||
private static void ValidateGameObject(GameObject gameObject, string scenePath, Report report)
|
private static void ValidateGameObject(GameObject gameObject, string scenePath, Report report)
|
||||||
{
|
{
|
||||||
ProjectValidatorUtility.AppendToScenePath(gameObject, ref scenePath);
|
ProjectValidatorUtility.AppendToScenePath(gameObject, ref scenePath);
|
||||||
ValidateComponents(gameObject, scenePath, report);
|
|
||||||
|
var assetGuid = EditorAssetUtility.GetAssetGuid(gameObject);
|
||||||
|
using var _ = ListPool<ValidatorResult>.Get(out var results);
|
||||||
|
|
||||||
|
for (var i = 0; i < _validatorList.GameObjectValidators.Count; i++)
|
||||||
|
{
|
||||||
|
results.Clear();
|
||||||
|
|
||||||
|
_validatorList.GameObjectValidators[i].Validate(gameObject, results);
|
||||||
|
var type = ProjectValidatorUtility.GetGameObjectValidatorName(_validatorList.GameObjectValidators[i]);
|
||||||
|
|
||||||
|
for (var j = 0; j < results.Count; j++)
|
||||||
|
{
|
||||||
|
var result = results[j];
|
||||||
|
|
||||||
|
if (result.Severity != EValidatorSeverity.Valid)
|
||||||
|
report.Add(assetGuid, scenePath, string.Empty, type, result.Severity, result.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ValidateComponents(gameObject, assetGuid, scenePath, report);
|
||||||
ValidateChildren(gameObject, scenePath, report);
|
ValidateChildren(gameObject, scenePath, report);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ValidateComponents(GameObject gameObject, string scenePath, Report report)
|
private static void ValidateComponents(GameObject gameObject, GUID assetGuid, string scenePath, Report report)
|
||||||
{
|
{
|
||||||
using var _ = ListPool<Component>.Get(out var components);
|
using var _ = ListPool<Component>.Get(out var components);
|
||||||
var assetGuid = EditorAssetUtility.GetAssetGuid(gameObject);
|
|
||||||
gameObject.GetComponents(components);
|
gameObject.GetComponents(components);
|
||||||
|
|
||||||
for (var i = 0; i < components.Count; i++)
|
for (var i = 0; i < components.Count; i++)
|
||||||
{
|
{
|
||||||
Validate(assetGuid, scenePath, components[i], report);
|
if (components[i] != null)
|
||||||
|
Validate(assetGuid, scenePath, components[i], report);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Module.ProjectValidator.Editor
|
||||||
|
{
|
||||||
|
internal sealed class ComponentValidatorSkinnedMeshRenderer : IComponentValidator<SkinnedMeshRenderer>
|
||||||
|
{
|
||||||
|
public void Validate(SkinnedMeshRenderer component, List<ValidatorResult> results)
|
||||||
|
{
|
||||||
|
var materials = component.sharedMaterials;
|
||||||
|
|
||||||
|
for (var i = 0; i < materials.Length; i++)
|
||||||
|
{
|
||||||
|
if (materials[i] == null)
|
||||||
|
results.Add(ValidatorResult.Create(EValidatorSeverity.Error, $"Missing material in slot #{i}"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (component.sharedMesh == null)
|
||||||
|
results.Add(ValidatorResult.Create(EValidatorSeverity.Error, "Missing mesh"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 1610561c53a0aa84aaa903e5dde29694
|
||||||
3
Editor/Validators/GameObject.meta
Normal file
3
Editor/Validators/GameObject.meta
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 45fa253dcfa349d5b1e9bd56ebac7c98
|
||||||
|
timeCreated: 1779133809
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Module.ProjectValidator.Editor
|
||||||
|
{
|
||||||
|
internal sealed class GameObjectValidatorBrokenPrefab : IGameObjectValidator
|
||||||
|
{
|
||||||
|
public void Validate(GameObject gameObject, List<ValidatorResult> results)
|
||||||
|
{
|
||||||
|
if (PrefabUtility.IsPrefabAssetMissing(gameObject))
|
||||||
|
results.Add(ValidatorResult.Create(EValidatorSeverity.Error, "GameObject is missing prefab asset"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 8fd1dfcd3d564622a918e2175499318d
|
||||||
|
timeCreated: 1779133864
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Module.ProjectValidator.Editor
|
||||||
|
{
|
||||||
|
internal sealed class GameObjectValidatorMissingComponents : IGameObjectValidator
|
||||||
|
{
|
||||||
|
public void Validate(GameObject gameObject, List<ValidatorResult> results)
|
||||||
|
{
|
||||||
|
var count = GameObjectUtility.GetMonoBehavioursWithMissingScriptCount(gameObject);
|
||||||
|
|
||||||
|
if (count != 0)
|
||||||
|
results.Add(ValidatorResult.Create(EValidatorSeverity.Error, $"GameObject is missing {count} component(s)"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 66cbc43729ec4e81a9e353e537b3ccf0
|
||||||
|
timeCreated: 1779133947
|
||||||
13
README.md
13
README.md
|
|
@ -9,6 +9,19 @@ A tool to help validate data across scenes, prefabs and scriptable objects.
|
||||||

|

|
||||||

|

|
||||||
|
|
||||||
|
## Game Object Validators
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public sealed class GameObjectValidatorBrokenPrefab : IGameObjectValidator
|
||||||
|
{
|
||||||
|
public void Validate(GameObject gameObject, List<ValidatorResult> results)
|
||||||
|
{
|
||||||
|
if (PrefabUtility.IsPrefabAssetMissing(gameObject))
|
||||||
|
results.Add(ValidatorResult.Create(EValidatorSeverity.Error, "GameObject is missing prefab asset"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## Component Validators
|
## Component Validators
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
|
|
|
||||||
10
Runtime/Interfaces/IGameObjectValidator.cs
Normal file
10
Runtime/Interfaces/IGameObjectValidator.cs
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Module.ProjectValidator
|
||||||
|
{
|
||||||
|
public interface IGameObjectValidator
|
||||||
|
{
|
||||||
|
void Validate(GameObject gameObject, List<ValidatorResult> results);
|
||||||
|
}
|
||||||
|
}
|
||||||
3
Runtime/Interfaces/IGameObjectValidator.cs.meta
Normal file
3
Runtime/Interfaces/IGameObjectValidator.cs.meta
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: f7513a02611842029edd675cb64989ad
|
||||||
|
timeCreated: 1779133097
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "com.module.project-validator",
|
"name": "com.module.project-validator",
|
||||||
"version": "0.2.0",
|
"version": "0.3.0",
|
||||||
"displayName": "Module.ProjectValidator",
|
"displayName": "Module.ProjectValidator",
|
||||||
"description": "",
|
"description": "",
|
||||||
"unity": "6000.3",
|
"unity": "6000.3",
|
||||||
|
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 232 KiB After Width: | Height: | Size: 154 KiB |
Loading…
Add table
Add a link
Reference in a new issue