Custom Rules

advanced feature

Editor Doctor Pro · Features

Custom Rules

Beyond the three native Conventions checks, EDP exposes a power-user rule engine. Compose predicates (what an asset matches on) with recipes (what EDP does about it) to author rules specific to your project's structure.

Model

A custom rule has three parts:

  • Id - EDP-USER-<your-id>. Stable across runs; used by the suppression store and report schema.
  • Predicate - one of five primitives, optionally combined via Not. Asset-level predicates evaluate against every asset under the scan scope.
  • Recipe - what EDP does when the predicate matches. Four primitives.

Predicates

PredicateArgumentMatches when
PathMatchespath globThe asset path matches the glob (e.g. Assets/Plugins/**, Assets/Game/Levels/**/*.unity).
IsTypetype nameThe asset's main type is the given Unity type (Texture2D, Material, SceneAsset, Prefab, MonoScript, etc.).
NamePrefixstringThe asset's file name starts with the given string (e.g. T_, M_, SO_).
HasComponentcomponent type nameThe asset is a prefab containing the given component type anywhere in its hierarchy.
Notanother predicateInverts a predicate.

Recipes

RecipeArgumentEffect
Flagseverity, messageEmits a finding with the given severity and human-readable message. No fix; review-only.
MoveAssetdestination folderManual fix: prompts confirmation, then runs AssetDatabase.MoveAsset to the destination. GUID-preserving.
Renamerename patternManual fix: prompts confirmation, then runs AssetDatabase.RenameAsset using the pattern (the {name} placeholder expands to the current filename without extension). GUID-preserving.
Ignore(none)Skip the asset entirely from every check. Useful for project-specific exclusions that don't fit the path-glob exclude list.

Example: keep textures out of /Prefabs

{
  "id": "no-textures-under-prefabs",
  "predicate": {
    "kind": "and",
    "left":  { "kind": "PathMatches", "glob": "Assets/Prefabs/**" },
    "right": { "kind": "IsType", "type": "Texture2D" }
  },
  "recipe": {
    "kind": "MoveAsset",
    "destination": "Assets/Textures"
  }
}

The rule fires on every Texture2D under Assets/Prefabs/ and offers a Manual fix to move it to Assets/Textures/.

Example: flag orphan ScriptableObjects in /Game

{
  "id": "no-orphan-so-in-game",
  "predicate": {
    "kind": "and",
    "left":  { "kind": "PathMatches", "glob": "Assets/Game/**" },
    "right": { "kind": "IsType", "type": "ScriptableObject" }
  },
  "recipe": {
    "kind": "Flag",
    "severity": "warn",
    "message": "ScriptableObject under Assets/Game/ - relocate to Assets/Game/Data/."
  }
}

Storage

Custom rules live in ProjectSettings/EditorDoctorPro/user-rules.json and are shared via git. The Settings UI reads / writes this file via the inline editor under Settings > Conventions > Custom Rules; you can also edit the JSON directly and reimport.

Reversibility

Move and rename recipes use AssetDatabase.MoveAsset and AssetDatabase.RenameAsset. Both preserve the GUID, so references in scenes / prefabs / serialized data follow the asset to its new path / name. Restore the action from the Action History Trash workflow.

Move asset is destructive. The Manual confirmation dialog lists every move before any file changes on disk. Read the list - rename and move recipes are GUID-preserving but a typo in the destination glob can sweep more assets than you intended.
Was this page helpful?