Creating custom analyzers
Add your own custom analyzers to Project Auditor.
Read time 4 minutesLast updated 13 days ago
Project Auditor provides an API for creating custom analyzers tailored to the needs of your project.
Internally, Project Auditor creates and maintains the following modules:
- Animation
- Assets
- AudioClip
- BuildReport
- Code
- Mesh
- Packages
- Settings
- Shader
- SpriteAtlas
- Texture
Every module has a corresponding class inheriting from which declares an method which takes a type inheriting from . During analysis, the module uses reflection to detect and create instances of any Analyzer classes inheriting from its corresponding , then constructs objects and passes them to the Analyzers.
ModuleAnalyzerAnalyzeAnalysisContextModuleAnalyzerAnalysisContextCreate an analyzer
The following is an example showing how to create a custom Analyzer. Imagine a texture-heavy 2D game with a pixel art visual style. In such a project it might be desirable to enforce maximum sizes for sprite texture assets to help manage memory and to enforce a consistent visual resolution.
The example script demonstrates how to do the following:
- Declare and register a , including its custom
Descriptor.Fixer - Use to declare a diagnostic parameter for use during analysis.
DiagnosticParameterAttribute - Access the contents of the structure passed to it to decide whether to report an issue.
context - Create an issue, including specifying the which dictates the view in which the issue appears and the information that is displayed in the Issue table.
IssueCategory
using System;using System.Collections.Generic;using Unity.ProjectAuditor.Editor;using Unity.ProjectAuditor.Editor.Core;using UnityEditor;// Inherit from TextureModuleAnalyzer to allow TextureModule to create and run an// instance of this analyzer.class CustomTextureAnalyzer : TextureModuleAnalyzer{ // Define our custom maximum sprite size const int k_MaxSpriteSize = 1024; // Data for constructing a descriptor. const string k_SpriteTooBigId = "PAA9000"; // Make sure this ID is unique. const string k_Title = "(Custom) Texture: Oversized Sprite"; const Areas k_ImpactedAreas = Areas.Memory | Areas.Quality; const string k_Description = "The source texture for this Sprite is larger than the limit specified by " + "the game's art direction. Oversized textures can take up too much memory " + "and compromise visual style."; const string k_Recommendation = "Resize the source texture, or set the <b>Max Size</b> option in the " + "Texture Import Settings to a suitable value."; // Declare a Descriptor to describe the issue we want to report. static readonly Descriptor k_CustomSpriteTooBigDescriptor = new Descriptor ( k_SpriteTooBigId, k_Title, k_ImpactedAreas, k_Description, k_Recommendation ) { // As well as the constructor parameters above, this area can be used to set // the values of other Descriptor fields. // Project Auditor will format this message using the Name that's passed into // CreateIssue. MessageFormat = "Sprite '{0}' is oversized", // Optionally declare a delegate to fix the issue in a single button click. Fixer = (issue, analysisParams) => { var textureImporter = AssetImporter.GetAtPath(issue.RelativePath) as TextureImporter; if (textureImporter != null) { textureImporter.maxTextureSize = k_MaxSpriteSize; textureImporter.SaveAndReimport(); } } }; // Declare m_CustomSpriteSizeLimit as a DiagnosticParam. Give the parameter a // unique name and a sensible default. [DiagnosticParameter("CustomSpriteSizeLimit", "Sprite Size Limit", "Warn if any sprites have a width or height greater than this value.", k_MaxSpriteSize)] int m_CustomSpriteSizeLimit; // Override the initialize method in order to pass the custom Descriptor to the // registerDescriptor Action so that ProjectAuditor knows about it. public override void Initialize(Action<Descriptor> registerDescriptor) { registerDescriptor(k_CustomSpriteTooBigDescriptor); } // Implementation of the custom Analyze coroutine method. In the case of a class // inheriting from TextureModuleAnalyzer, the AnalysisContext passed to this // method is a TextureAnalysisContext. public override IEnumerable<ReportItem> Analyze(TextureAnalysisContext context) { // Check to see if a texture is treated as a sprite, and check its dimensions if (context.Importer.textureType == TextureImporterType.Sprite && (context.Texture.width > m_CustomSpriteSizeLimit || context.Texture.height > m_CustomSpriteSizeLimit)) { // Create the issue with the correct category, DescriptorId, name and path yield return context.CreateIssue(IssueCategory.AssetIssue, k_CustomSpriteTooBigDescriptor.Id, context.Name) .WithLocation(context.Importer.assetPath); } }}

Custom analyzer output
Debugging slow analyzers
The analysis for some issues might take a long time to run, particularly in a large project. The for such issues might declare to be false to stop them running when running Project Auditor interactively in the Editor.
DescriptorDescriptor.IsEnabledByDefaultWhen running Project Auditor in a CI/CD environment you can re-enable analysis for these descriptors. Use to add temporary instances to increase the of a Descriptor to anything other than to re-enable analysis in this context.
AnalysisParams.WithAdditionalDiagnosticRulesRuleSeveritySeverity.NoneWriting Descriptor text
Use the following guidelines when writing the strings that appear in Descriptors for the Issues the tool reports:
- Use bold for the name of APIs and settings options in both the description and the recommendation. Do this by adding and
<b>tags before and after the name.</b> - Don’t use rich text in title or strings. No
messageFormatbold<b>tags, for example. These fields don’t support rich text in the UI so it will look bad.</b>