Project Health & Integrity for Unity — find issues, clean garbage, track references, and guard your builds.
After importing from the Asset Store, Sentinel lives at Assets/Sentinel/. Unity will compile the YourStudio.Sentinel.Editor assembly automatically. No setup required.
Go to Window > Sentinel > Open Window or press Ctrl+Shift+Alt+S.
The main window has a toolbar and four tabs: Health, Issues, Unused Assets, and Dependencies.
The Issues tab scans your entire project — including closed scenes (via YAML parsing, without opening them) — and reports problems organized by severity.
| Detector | Default Severity | What It Finds |
|---|---|---|
| Missing Script | Error | GameObjects with deleted/renamed MonoBehaviour scripts |
| Missing Reference | Error | Serialized fields pointing to destroyed/missing assets |
| Missing Material | Error | Renderers with null material slots |
| Shader Error | Error | Shaders that fail to compile |
| Empty UnityEvent | Warning | UnityEvent fields with zero persistent listeners |
| Invalid Layer | Warning | GameObjects assigned to undefined layer indices |
| Invalid Tag | Warning | GameObjects with tags that don't exist in the Tag Manager |
| Unused Component | Warning | Lone MonoBehaviours on childless leaf GameObjects |
| Empty GameObject | Info | GameObjects with only a Transform and no children |
| Duplicate Name | Info | Multiple assets sharing the same filename |
| Column | Description |
|---|---|
| Type | The issue detector name (e.g., MissingScript, MissingRef) |
| Asset Path | Full project path to the asset (e.g., Assets/Scenes/Level1.unity) |
| Object Type | The Unity asset type (e.g., SceneAsset, GameObject, MonoScript) |
| Message | Human-readable description of the issue |
Click any column header to sort by that column. Click again to reverse the sort order.
The left panel provides filters:
Issues that have automatic fixes show a "Fix:" option when right-clicked:
All fixes support Undo (Ctrl+Z). After any fix is applied, Sentinel automatically rescans the project and shows a popup confirming how many issues were resolved.
The "Fix All Auto-Fixable" button in the left panel applies the first available fix for every fixable issue at once.
Right-click any issue and select "Suppress Issue" to hide it from future scans. Suppressions are saved to Assets/SentinelData/suppressions.json (version-controlled, shared with your team).
To remove a suppression, enable the "Suppressed" filter, find the issue, right-click, and select "Remove Suppression."
Right-click any issue row for:
Clicking any row pings the asset in the Project window.
The Unused Assets tab finds unreferenced assets — files that are not reachable from any build scene, Resources folder, or other root — and are safe to delete.
Sentinel uses a root-tracing algorithm:
AssetDatabase.GetDependenciesResources/ folders and their dependenciesStreamingAssets/, Editor/, Plugins/, Gizmos/.cs, .asmdef, .asmref)When you click "Delete Selected," a confirmation dialog appears with two options:
Assets are moved to Assets/SentinelTrash/ where you can review them. To restore, simply move them back. To permanently delete later, remove the folder manually.
Assets are deleted from the project. A backup ZIP is automatically created at Library/SentinelBackups/ before deletion.
Click "Open Full Preview Window" for a larger, dedicated window with:
The Dependencies tab answers: "Where is this asset used?"
Sentinel rebuilds the dependency map fresh each time you search, so it always reflects the current project state. It also performs a supplementary YAML search across all scene and prefab files to catch references that the map might miss.
The Health tab tracks your project's health over time.
A score from 0 to 100 calculated after each scan:
Score = 100 - (Errors × 5) - (Warnings × 1) - (Infos × 0.2) clamped to [0, 100]
Project is in good shape. Few or no critical issues.
Some issues accumulating. Schedule cleanup time.
Significant issues. Address errors before shipping.
Shows whether issues increased or decreased since the previous scan.
After 2+ scans, a line chart shows errors (red), warnings (yellow), and total issues (white) over time. Sentinel stores up to 60 scan snapshots.
Lock a baseline to establish "known issues." Future scans will report how many new issues appeared since the baseline was locked. This is especially useful for CI pipelines: allow existing tech debt but block new regressions.
Assets/SentinelData/baseline.json (version-controlled)Go to Edit > Project Settings > Sentinel to configure.
Assets)Assets/Sandbox)Override the default severity for each issue type. For example, change "Empty UnityEvent" from Warning to Info if your project uses event-driven patterns where empty events are intentional.
| Option | Default | Description |
|---|---|---|
| Scan Open Scenes | On | Include currently open scenes in the scan |
| Scan Closed Scenes | On | Scan .unity files via YAML (without opening them) |
| Auto Scan on Compile | Off | Trigger a scan after every script compilation |
| Fail Build on Errors | Off | Block player builds if Error-severity issues exist |
Paste a Slack or Discord webhook URL to receive scan result notifications. Click "Test Webhook" to verify.
When "Fail Build on Errors" is enabled, Sentinel runs a fast pre-build scan (Missing Scripts + Missing References only) before every player build. If errors are found, the build is blocked with a summary of issues.
Add the [SentinelIgnore] attribute to fields, properties, or entire classes to suppress issue detection:
[SentinelIgnore("Intentionally null during async loading")]
public GameObject optionalReference;
Right-click assets or folders in the Project window:
Run Sentinel in headless mode for CI pipelines:
Unity.exe -batchmode -quit -projectPath /path/to/project \ -executeMethod YourStudio.Sentinel.Editor.SentinelCLI.RunScan \ -sentinelOutput Reports/sentinel-report.json \ -sentinelFailOn Error
| Argument | Default | Description |
|---|---|---|
-sentinelOutput | sentinel-report.json | Output path for the JSON report |
-sentinelFailOn | Error | Minimum severity to fail (Error, Warning, Info) |
| Code | Meaning |
|---|---|
0 | Scan passed — no issues at or above the fail threshold |
1 | Scan failed — issues found at or above the fail threshold |
2 | Scan error — crash, missing profile, or configuration problem |
Two reports are generated side by side:
Machine-readable. Contains scan date, Unity version, duration, issue summary (errors/warnings/infos/suppressed), new-since-baseline count, and the full issues array.
Standard test result format. Compatible with GitHub Actions (dorny/test-reporter), Jenkins, GitLab CI. Includes file attributes for inline PR annotations and a <properties> block with scan metadata.
A ready-to-use workflow is included at Assets/Sentinel/CI/sentinel-ci.yml. Copy it to .github/workflows/sentinel-ci.yml in your repository. It uses Game CI (game-ci/unity-builder@v4).
Unity.exe -batchmode -quit -projectPath /path/to/project \ -executeMethod YourStudio.Sentinel.Editor.SentinelCLI.LockBaseline
Sentinel can install a git hook that automatically runs a health scan after every git pull / git merge. Call SentinelGitHook.InstallPostMergeHook() from code or a menu item.
Sentinel's detector system is fully extensible. Create your own detectors to enforce project-specific rules — naming conventions, component limits, folder structure, and more. Custom extensions are auto-discovered via TypeCache — no registration, no config files.
.asmdef) that references YourStudio.Sentinel.Editor and targets the Editor platform onlySentinelExtensionBaseDetectorName and whichever lifecycle hooks you needAddIssue() to report problems| Member | Description |
|---|---|
DetectorName required | Unique string identifying your detector (e.g., "NamingConvention") |
OnScanStart(ctx) | Called once when a scan begins. Use it to load settings or initialize state. |
OnAssetScanned(assetPath, so) | Called for every asset in the project. so is the SerializedObject (may be null for non-serializable assets). |
OnPrefabScanned(prefabPath, root) | Called for each prefab with its root GameObject. |
OnSceneScanned(scenePath, rootObjects) | Called for each open scene with its root GameObject[] array. |
OnSceneTextScanned(scenePath, sceneText) | Called for each closed scene with its raw scene-file text (YAML) as a string. |
OnScanEnd(ctx) | Called once after all assets have been scanned. Use for project-wide checks. |
AddIssue(record) | Reports an issue. Sentinel assigns a unique ID automatically. |
using System.IO;
using UnityEditor;
namespace YourStudio.Sentinel.Editor
{
public class NamingConventionDetector : SentinelExtensionBase
{
public override string DetectorName => "NamingConvention";
private SentinelSeverityConfig _severityConfig;
public override void OnScanStart(SentinelScanContext ctx)
{
_severityConfig = SentinelProjectSettings.GetOrCreate().SeverityConfig;
}
public override void OnAssetScanned(string assetPath, SerializedObject so)
{
string fileName = Path.GetFileNameWithoutExtension(assetPath);
// Prefabs should use PascalCase and have no spaces
if (assetPath.EndsWith(".prefab") && fileName.Contains(" "))
{
AddIssue(new SentinelIssueRecord
{
Severity = _severityConfig.GetSeverity("NamingConvention"),
IssueType = "NamingConvention",
AssetPath = assetPath,
Message = $"Prefab '{fileName}' contains spaces"
});
}
}
}
}
Your custom extension needs its own .asmdef file to reference the Sentinel assembly:
{
"name": "MyProject.SentinelExtensions",
"rootNamespace": "",
"references": [ "YourStudio.Sentinel.Editor" ],
"includePlatforms": [ "Editor" ],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}
.asmdef. This keeps it separate from Sentinel internals and makes upgrades easier.
| Field | Type | Description |
|---|---|---|
Severity | SentinelIssueSeverity | Error, Warning, or Info. Use SeverityConfig.GetSeverity() to let users override. |
IssueType | string | Must match your DetectorName. |
AssetPath | string | Full asset path (e.g., Assets/Prefabs/Player.prefab). |
ObjectPath | string | (Optional) Path within the asset (e.g., GameObject name). |
Message | string | Human-readable description shown in the Issues tab. |
Sentinel ships with three example detectors in Assets/Sentinel/SentinelExtensionDemo/. These serve as both documentation and real, functional detectors you can modify or use as templates:
Uses OnAssetScanned to enforce naming rules: no spaces in prefab names, M_/Mat_ prefix for materials, T_ prefix for textures. Demonstrates how to use SeverityConfig.GetSeverity() so users can override severity per-project.
Uses OnPrefabScanned to flag prefabs exceeding a component threshold (default: 10). Demonstrates the prefab lifecycle hook and GetComponentsInChildren traversal.
Uses OnScanEnd to recursively scan for empty folders project-wide. Demonstrates the end-of-scan hook for checks that don't map to individual assets.
The [SentinelIgnore] attribute can be applied to fields, properties, or entire classes to suppress issue detection for specific references:
using UnityEngine;
#if UNITY_EDITOR
using YourStudio.Sentinel.Editor;
#endif
public class MyComponent : MonoBehaviour
{
[Tooltip("This reference is intentionally null at edit time")]
#if UNITY_EDITOR
[SentinelIgnore("Assigned at runtime via Addressables")]
#endif
public GameObject DynamicPrefab;
}
[SentinelIgnore] in #if UNITY_EDITOR to avoid including the attribute in player builds, since it lives in an editor-only assembly.
A complete working example is included at Assets/Sentinel/SentinelExtensionDemo/SentinelIgnoreDemo.cs.
| Shortcut | Action |
|---|---|
| Ctrl+Shift+Alt+S | Open Sentinel window |
| Menu Path | Action |
|---|---|
| Window > Sentinel > Open Window | Opens the main Sentinel window |
| Window > Sentinel > Install Git Post-Merge Hook | Installs a git hook that runs a scan after every pull / merge |
| Tools > Sentinel > CI > Run Scan (Headless) | Runs a scan and writes reports (same as the CLI entry point) |
| Tools > Sentinel > CI > Lock Baseline (Headless) | Locks the current issue state as baseline |
| Edit > Project Settings > Sentinel | Opens Sentinel settings |
| Assets > Sentinel > Exclude Folder from Scans | Right-click context menu on folders |
| Assets > Sentinel > Suppress All Issues in This Asset | Right-click context menu on assets |
| File | Location | Version Controlled? | Purpose |
|---|---|---|---|
SentinelDependencyCache.json | Library/ | No | Dependency graph cache (JSON) |
SentinelSettings.json | ProjectSettings/ | Yes | Shared scan configuration |
suppressions.json | Assets/SentinelData/ | Yes | Shared issue suppressions |
baseline.json | Assets/SentinelData/ | Yes | Shared issue baseline |
SentinelTrends.asset | UserSettings/ | No | Per-developer scan history |
SentinelUserSettings.asset | UserSettings/ | No | Per-developer UI preferences |
SentinelBackups/*.zip | Library/ | No | Pre-deletion backup archives |
SentinelTrash/ | Assets/ | Optional | Reversible trash folder |
No. Sentinel is entirely editor-only. The assembly definition restricts it to the Editor platform. Nothing is included in player builds.
Only when you explicitly use a fix action (e.g., "Remove Missing Script" or "Clear Reference"). All fixes support Undo. The cleaner only deletes assets you manually select and confirm.
Sentinel reads .unity files as raw YAML text and uses regex patterns to extract missing script GUIDs and broken references. It never calls EditorSceneManager.OpenScene(), so it's fast (50+ scenes per second) and doesn't disrupt your current scene.
Yes. Create a class that extends SentinelExtensionBase, override the DetectorName property and whichever On*Scanned methods you need, and call AddIssue(). Sentinel discovers it automatically via TypeCache — no registration needed.
Make sure the scene or prefab using that asset is saved. The dependency tracer reads files on disk, not unsaved in-memory state. Also check that the using scene is in your Build Settings.
If you used "Move to Trash," the assets are in Assets/SentinelTrash/ — move them back manually. If you used "Delete Permanently," a backup ZIP exists at Library/SentinelBackups/.
Contact us at ragendom@gmail.com
Please include: