Skip to content

jetstyle/unity-build-validation

Repository files navigation

BuildValidation

BuildValidation is a JetXR Unity package for checking project-specific validation rules before a player build is created.

The package adds attributes that mark serialized Unity object references as required and validation methods as build checks. During a build, BuildValidation scans build content and reports every issue it finds. Fatal validation issues stop the build after the scan is complete.

Installation

Install the package through Unity Package Manager from the Git repository:

https://github.com/jetstyle/unity-build-validation.git

In Unity:

  1. Open Window > Package Manager.
  2. Click +.
  3. Select Add package from git URL....
  4. Enter the repository URL.

The package name is:

style.jetxr.buildvalidation

Usage

Add the namespace to a runtime script:

using JetXR.Unity.BuildValidation;
using UnityEngine;

public sealed class ExampleMapSettings : MonoBehaviour
{
    [ValidateReferenceSet]
    public Texture2D requiredMap;
}

When no severity is provided, the attribute uses ReferenceValidationSeverity.Fatal.

The attribute can be used on serialized fields that store Unity object references:

[ValidateReferenceSet(ReferenceValidationSeverity.Fatal)]
[SerializeField] Material requiredMaterial;

[ValidateReferenceSet("Main audio clip is required for this asset.")]
public AudioClip mainClip;

[ValidateReferenceSet(ReferenceValidationSeverity.Info)]
public AudioClip[] clips;

[ValidateReferenceSet(ReferenceValidationSeverity.Warning)]
public List<GameObject> prefabs;

Fields must be serialized by Unity. Public fields and private fields with [SerializeField] are supported. Static fields and non-serialized fields are ignored.

Direct ExposedReference<T> fields are not checked by the base reference validator. If com.unity.timeline is installed, the package adds a built-in TimelineReferencesValidator that checks timeline references through PlayableDirector.

Use [ValidateInvoke] when validation logic needs code:

using JetXR.Unity.BuildValidation;
using UnityEngine;

public sealed class ExampleMapSettings : MonoBehaviour
{
    public Texture2D requiredMap;

    [ValidateInvoke]
    private BuildValidationResult OnBuildValidate()
    {
        if (requiredMap == null)
            return BuildValidationResult.Fatal("Required map is missing.");

        return BuildValidationResult.Pass();
    }
}

Methods marked with [ValidateInvoke] must be instance methods without parameters and must return BuildValidationResult. They can be public, protected, or private. BuildValidation calls these methods explicitly before the build; Unity runtime lifecycle methods such as Awake, Start, and OnEnable are not part of the validation contract.

Use BuildTypeValidator when validation logic should live in an editor-only script and apply to every object of a specific Unity type:

using JetXR.Unity.BuildValidation;
using JetXR.Unity.BuildValidation.Editor;
using UnityEngine;

[BuildTypeValidator(typeof(ExampleMapSettings))]
public sealed class ExampleMapSettingsBuildTypeValidator : BuildTypeValidator<ExampleMapSettings>
{
    protected override BuildValidationResult Validate(ExampleMapSettings target, BuildTypeValidationContext context)
    {
        if (target.requiredMap == null)
            return BuildValidationResult.Fatal("Required map is missing.");

        return BuildValidationResult.Pass();
    }
}

BuildTypeValidator classes must be in editor assemblies. The attribute binds a validator to the target type. Passing useForChildren: true also applies the validator to derived Unity object types.

Multiple validators can target the same type. The object is valid only when all enabled validators pass.

Use BuildTypeValidator<T, TSettings> when a validator needs project-level parameters. Settings must be serializable classes derived from BuildTypeValidatorSettings:

using System;
using JetXR.Unity.BuildValidation;
using JetXR.Unity.BuildValidation.Editor;
using UnityEngine;

[Serializable]
public sealed class ExampleMapSettingsValidatorSettings : BuildTypeValidatorSettings
{
    public ReferenceValidationSeverity missingPreviewSeverity = ReferenceValidationSeverity.Warning;
}

[BuildTypeValidator(typeof(ExampleMapSettings))]
public sealed class ExampleMapSettingsValidator
    : BuildTypeValidator<ExampleMapSettings, ExampleMapSettingsValidatorSettings>
{
    protected override BuildValidationResult Validate(
        ExampleMapSettings target,
        ExampleMapSettingsValidatorSettings settings,
        BuildTypeValidationContext context)
    {
        if (target.previewMap == null)
            return BuildValidationResult.Issue(settings.missingPreviewSeverity, "Preview map is missing.");

        return BuildValidationResult.Pass();
    }
}

Use BuildTypeValidationContext when one validator needs to report multiple issues:

protected override BuildValidationResult Validate(ExampleMapSettings target, BuildTypeValidationContext context)
{
    if (target.requiredMap == null)
        context.Fatal("Required map is missing.");

    if (target.previewMap == null)
        context.Warning("Preview map is missing.");

    return BuildValidationResult.Pass();
}

Build type validators can be enabled or disabled in:

Project Settings > Build Validation

Validator settings are opened with the settings button on the right side of the validator row. The expanded/collapsed state is not saved. If a validator is disabled, its settings are hidden from the panel but kept in ProjectSettings/BuildValidationSettings.asset.

Manual Validation

Run validation without starting a build from:

Tools/Validation/Validate Required References For Build

The same validation path is used for manual validation and build validation.

Build Behavior

BuildValidation checks:

  • enabled scenes from Build Settings;
  • MonoBehaviour components in those scenes;
  • prefabs included through build dependencies;
  • ScriptableObject assets included through build dependencies;
  • other serialized Unity object assets included through build dependencies;
  • assets under Resources, even when they are not referenced by a scene.
  • enabled BuildTypeValidator validators for every checked Unity object with a matching type.

When com.unity.timeline is installed, the built-in TimelineReferencesValidator also checks PlayableDirector components:

  • timeline track bindings shown in the Timeline inspector must be assigned;
  • [ValidateReferenceSet] on ExposedReference<T> fields inside timeline assets and sub-assets must resolve through the director.

TimelineReferencesValidator has project settings for enabling binding checks, enabling exposed reference checks, and choosing the severity for missing timeline bindings.

For each issue, the Unity Console receives a message with the severity, asset or scene path, object path, component or asset type, and the field or method that reported the issue. Console messages use the relevant Unity object as context, so selecting the log entry can ping or select the related asset or object.

If a custom fail message is passed to the attribute, that message is written as the first line of the Console entry. The default validation details are written after it.

Severity controls the build result:

  • Info logs a regular Console message and does not appear in the final validation summary.
  • Warning logs a warning and does not fail the build.
  • Fatal logs an error and fails the build after all validation issues have been reported.

Array and List<T> fields are checked per element. Empty arrays and lists are valid. Null elements are reported with their element index.

Invalid [ValidateInvoke] method signatures and exceptions thrown by validation methods are reported as Fatal.

Invalid BuildTypeValidator definitions and exceptions thrown by build type validators are reported as Fatal.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages