Code Monkey home page Code Monkey logo

dtvalidator's Introduction

DTValidator

Tool for validating (ensuring no broken / missing outlets) objects like GameObjects, ScriptableObjects, etc, in the Unity Editor.

Why use DTValidator?

It's so easy to break outlets by renaming functions, removing assets, losing .meta files, etc. DTValidator finds missing outlets (any UnityEngine.Object exposed in the inspector), broken UnityEvents, and missing MonoBehaviour scripts.

More importantly, it's easy to set it up as a unit test for integration with your build pipeline.

Read more about DTValidator here.

To Install & Use:

  1. Download the DTValidator project from this repository by pressing this link. It should automatically download the latest state of the master branch.
  2. Place the downloaded folder in your project. I recommend placing it in the Assets/Plugins directory so it doesn’t add to your compile time

Now you have unit tests running to validate your project! Try running them by opening the Test Runner window under Window->Test Runner. It's likely that you'll have errors in your project - that's okay! Most likely the errors will be outlets that you need to mark [DTValidator.Optional]. See the FAQ for the best approach to deal with these errors.

To find and fix these errors, open the DTValidator Window under Window->DTValidator Window.

DTValidator Window Menu Item

Now press the Validate button and all the errors will show up. You can see where the error originated from and even highlight the object in the editor. Go through each error and determine if it’s an actual error or if it needs to be marked [DTValidator.Optional].

Image of Errors in DTValidator Window

Once you’re left with no errors, you’re done! Now set your build system to run unit tests for every build. You can now easily find and check new validation errors when they come up.

FAQ

Q: I have an outlet marked as an error, but it's fine that the outlet is missing. How do I fix this?

A: Mark the outlet as [DTValidator.Optional] and the validator will ignore checking the field.

public class ExampleMonoBehaviour : MonoBehaviour {
	[DTValidator.Optional]
	public GameObject OptionalOutlet;

	[SerializeField, DTValidator.Optional]
	private GameObject optionalOutlet_;
}

Q: There are a ton of optional outlets for this plugin I downloaded, is there an easier way to deal with these errors?

A: Yup! Mark the entire plugin namespace as optional by creating a ValidatorIgnoredNamespace. Right-click in your project and go to Create->DTValidator->ValidatorIgnoredNamespace.

Create a ValidatorIgnoredNamespace

Q (advanced): There's an outlet that is usually required, but in certain conditions it's optional.. can we handle that case?

A: Yep, though it'll take a bit of code. You can add define a function that determines whether the type / field combination should be validated. Here's an example:

using DTValidator;

// This attribute lets Unity know to call the static constructor
// when the Editor starts up, therefore injecting the predicate DontValidateIfMeshRenderer
[InitializeOnLoad]
public static class IgnoreMeshFilterSharedMeshWhenMeshRendererExists {
	static ValidateMeshFilterSharedMesh() {
		MemberInfo sharedMeshMember = ValidatorUnityWhitelist.GetPropertyFrom(typeof(UnityEngine.MeshFilter), "sharedMesh");
		ValidatorPredicates.RegisterPredicateFor(sharedMeshMember, DontValidateIfMeshRenderer);
	}

	private static bool DontValidateIfMeshRenderer(object obj) {
		UnityEngine.Component component = obj as UnityEngine.Component;
		if (component == null) {
			return true; // should validate
		}

		MeshRenderer meshRenderer = component.GetComponent<MeshRenderer>();
		// should validate (true) when meshRenderer does not exist
		return meshRenderer == null;
	}
}

See the default included whitelisted classes (under DefaultIncluded/WhitelistedTypes) for more examples!


Q (advanced): I found an error that the validator doesn't mark as an error!

A: Is it a field on a Unity component? By default, nearly all Unity components are ignored by the validator because you can't mark fields as [Optional]. But you can pick specific type / field combinations for the validator to validate. Here's an example:

using DTValidator;

// This attribute lets Unity know to call the static constructor
// when the Editor starts up, therefore injecting MeshFilter->sharedMesh to be validated
[InitializeOnLoad]
public static class ValidateMeshFilterSharedMesh {
	static ValidateMeshFilterSharedMesh() {
		Type meshFilterType = typeof(UnityEngine.MeshFilter);
		MemberInfo sharedMeshMember = ValidatorUnityWhitelist.GetPropertyFrom(meshFilterType, "sharedMesh");
		ValidatorUnityWhitelist.RegisterWhitelistedTypeMember(meshFilterType, sharedMeshMember);
	}
}

See the default included whitelisted classes (under DefaultIncluded/WhitelistedTypes) for more examples!

Q (cont): It's not a field on a Unity component!

A: Open an issue with your specific case and I'll take a look at it 😁.


Don't see your question answered here? Open an issue!

dtvalidator's People

Contributors

blablubbabc avatar darrentsung avatar fl00f avatar mattoubatou avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

dtvalidator's Issues

Possibility to select what to check

First of all, thanks for the wonderful plugin, and useful articles!
It would be useful to have the option to select what the validator checks on.

For instance, it now checks on 'None' values in fields. For existing projects, it is quite cumbersome to mark all those fields with an attribute. Could it be an idea to have options to select which validations have to be checked? E.g. only events and missing scripts, not fields

DTValidator not detecting invalid serialized null field on serialized Serializable class instance inside of MonoBehviour.

Prefab Prefab contains MonoBehaviour Component.

Component contains private [SerializeField] serializeableInnerClassInstance which is an instance of [System.Serializable] class InnerClass which is defined nested inside of class OuterClass.

InnerClass contains [SerializeField] field, which is set to None in the Unity Inspector.

DTValidator isn't catching the invalid null field OuterClass.InnerClass.field.

Thanks!

Requests

Hi Darren,

this is really really good; I've been annoyed with unity's lack of information on missing outlets and this solves all those issues; Now there are couple of things that would just make this perfect.

  1. Instead of IgnoredNamespace have a ProcessOnlyNamespace; way too many developers in Unity writes their code without namespace - even things like SteamVR; So it would be more useful if I can get this to validate only my namespace.

  2. Option to scan scenes only in build and not saved scenes - as some assets come with demo scenes that at times we leave within project; no point of validator checking them.

Thanks again.
Rana

Internal UnityEvent tests fail

Hey,
beforehand, I am new to Unity and Unit testing in C#/Unity, so maybe I am missing something here.

I imported this project into one of my Unity projects and ran the Tests as suggested in the Readme. But the UnityEvent related internal tests fail (Screenshot: https://prnt.sc/10x8xog)

I haven't looked into this too deeply myself yet, but these tests seem to use reflection and rely on Unity internals, so maybe this is caused by the Unity version I am using: 2020.2.4f1
Edit: Seems like the method signature of this internal RegisterVoidPersistentListener has changed at some point: Unity-Technologies/UnityCsReference@2dce988

The error seems to be the same for all of these tests. Example strack trace:

EventWithSameName_ResolvesCorrectly (0,020s)
---
System.Reflection.TargetParameterCountException : Number of parameters specified does not match the expected number.
---
at System.Reflection.MonoMethod.ConvertValues (System.Reflection.Binder binder, System.Object[] args, System.Reflection.ParameterInfo[] pinfo, System.Globalization.CultureInfo culture, System.Reflection.BindingFlags invokeAttr) [0x00016] in <9577ac7a62ef43179789031239ba8798>:0 
  at System.Reflection.MonoMethod.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00011] in <9577ac7a62ef43179789031239ba8798>:0 
  at System.Reflection.MethodBase.Invoke (System.Object obj, System.Object[] parameters) [0x00000] in <9577ac7a62ef43179789031239ba8798>:0 
  at DTValidator.Internal.UnityEventReflectionExtensions.AddVoidPersistentListener (UnityEngine.Events.UnityEventBase unityEvent, UnityEngine.Object targetObj, System.String methodName) [0x0001a] in H:\GameDev\Unity\WizardBros\src\WizardBros\Assets\Plugins\DTValidator\Core\Extensions\UnityEventReflectionExtensions.cs:21 
  at DTValidator.Internal.PersistentListenerValidationTests.EventWithSameName_ResolvesCorrectly () [0x00015] in H:\GameDev\Unity\WizardBros\src\WizardBros\Assets\Plugins\DTValidator\Tests\Editor\PersistentListenerValidationTests.cs:62 
  at (wrapper managed-to-native) System.Reflection.MonoMethod.InternalInvoke(System.Reflection.MonoMethod,object,object[],System.Exception&)
  at System.Reflection.MonoMethod.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00032] in <9577ac7a62ef43179789031239ba8798>:0

Thanks in advance for looking into this

Edit:
Changing line UnityEventReflectionExtensions.cs:21 to kRegisterVoidListenerMethod.Invoke(persistentCalls, new object[] { 0, targetObj, typeof(UnityEngine.Object), methodName }); seems to fix the test cases. However, maybe there is a way to avoid relying on these Unity internals in the first place ..

Validator Window very slow while scrolling

This seems like a cool project but I can't really use it since the list that is being produces is so slow to scroll, I can't really get anywhere (really, like 1 frame per second or so is rendered). The project is not super huge but there are quite a few entries in the list from prefabs etc.

Importing repo cause lots of errors

when I tried to install this tool, I downloaded files and put them inside Assets\Plugins.
Then, lots of compilation errors happened.
I think this tool has dependencies like you should install other packages to work (ex: Unity TestFramework or NUnit,........) and there is no information about this!

Ignore Class

Thank you for the great work. Is there a possibility to ignore a class? I have the use-case that derivations from 3rd party classes also bring errors and then its not possible to make exposed variables (from the parent-class) optional. How do you handle such a case? The only solution which comes to my mind is to open a new namespace for those derived classes and solve it with IgnoreNamespace, but thats actually not what I want to do.

Null Ref error when selecting missing script error in editor

Unity 2017.1.1f1

NullReferenceException: Object reference not set to an instance of an object
DTValidator.Internal.IValidationErrorExtensions+c__AnonStorey0.<>m__0 (UnityEngine.Object o) (at Assets/Plugins/DTValidator-master/Validation/Editor/ValidationErrors/IValidationErrorExtensions.cs:88)
System.Linq.Enumerable+c__Iterator1D1[UnityEngine.Object].MoveNext () DTValidator.Internal.IEnumerableGenericExtensions.FirstOrDefault[Object] (IEnumerable1 enumerable, System.Predicate`1 predicate) (at Assets/Plugins/DTValidator-master/Core/Extensions/IEnumerableGenericExtensions.cs:10)
DTValidator.Internal.IValidationErrorExtensions.SelectObjectInEditor (IValidationError validationError) (at Assets/Plugins/DTValidator-master/Validation/Editor/ValidationErrors/IValidationErrorExtensions.cs:89)
DTValidator.Internal.IValidationErrorExtensions.SelectInEditor (IValidationError validationError) (at Assets/Plugins/DTValidator-master/Validation/Editor/ValidationErrors/IValidationErrorExtensions.cs:50)
DTValidator.ValidatorWindow.OnGUI () (at Assets/Plugins/DTValidator-master/Validation/Editor/ValidatorWindow.cs:123)
System.Reflection.MonoMethod.Invoke (System.Object obj, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Reflection/MonoMethod.cs:222)
Rethrow as TargetInvocationException: Exception has been thrown by the target of an invocation.
System.Reflection.MonoMethod.Invoke (System.Object obj, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Reflection/MonoMethod.cs:232)
System.Reflection.MethodBase.Invoke (System.Object obj, System.Object[] parameters) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Reflection/MethodBase.cs:115)
UnityEditor.HostView.Invoke (System.String methodName, System.Object obj) (at C:/buildslave/unity/build/Editor/Mono/HostView.cs:272)
UnityEditor.HostView.Invoke (System.String methodName) (at C:/buildslave/unity/build/Editor/Mono/HostView.cs:265)
UnityEditor.HostView.InvokeOnGUI (Rect onGUIPosition) (at C:/buildslave/unity/build/Editor/Mono/HostView.cs:232)

Also it would be nice to have some more information on objects with missing scripts other than just
"Missing MonoScript!"

Please offer a release as a downloadable DLL

Consumers should have other options for downloading and installing this awesome tool. Source is one option, but now thanks to asmdefs, it's easier to compile the project to a DLL and simply distribute that if users wish ( a far easier deployment model)

Or alternatively as a prepackaged asset file, already prepacked in the Plugins folder.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.