├── Editor
├── AssetCheckerSettings.cs.meta
├── AssetCheckerWindow.GUI.cs.meta
├── ResultTypeIconStyle.cs
├── BuiltinProviders.meta
├── GBG.AssetChecker.Editor.asmdef.meta
├── AssetChecker.cs.meta
├── AssetProvider.cs.meta
├── AssetCheckResult.cs.meta
├── CheckResultStats.cs.meta
├── CheckResultType.cs.meta
├── CustomViewProvider.cs.meta
├── ResultTypeIconStyle.cs.meta
├── AssetCheckerLocalCache.cs.meta
├── CheckResultDetailsView.cs.meta
├── CheckResultEntryView.cs.meta
├── BuiltinProviders
│ ├── ExplicitAssetProvider.cs.meta
│ ├── SelectionAssetProvider.cs.meta
│ ├── TextSearchAssetProvider.cs.meta
│ ├── ExplicitAssetProvider.cs
│ ├── SelectionAssetProvider.cs
│ └── TextSearchAssetProvider.cs
├── AssetProvider.cs
├── AssetCheckerWindow.cs.meta
├── GBG.AssetChecker.Editor.asmdef
├── CustomViewProvider.cs
├── AssetCheckResult.cs
├── AssetCheckerSettings.cs
├── CheckResultStats.cs
├── CheckResultEntryView.cs
├── AssetCheckerLocalCache.cs
├── CheckResultType.cs
├── AssetChecker.cs
├── AssetCheckerWindow.cs
├── AssetCheckerWindow.GUI.cs
└── CheckResultDetailsView.cs
├── Documents~
└── imgs
│ ├── img_sample_asset_checker_window.png
│ └── img_sample_asset_checker_new_settings.png
├── LICENSE.meta
├── README.md.meta
├── README_CN.md.meta
├── package.json.meta
├── Editor.meta
├── package.json
├── LICENSE
├── .gitignore
├── README_CN.md
└── README.md
/Editor/AssetCheckerSettings.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: e75c0a47d71a4625a6c7a43a57b3f80f
3 | timeCreated: 1714195280
--------------------------------------------------------------------------------
/Editor/AssetCheckerWindow.GUI.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: fedf1df82f184a37bd48c5946ebf0b9c
3 | timeCreated: 1714199142
--------------------------------------------------------------------------------
/Documents~/imgs/img_sample_asset_checker_window.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SolarianZ/UnityAssetChecker/HEAD/Documents~/imgs/img_sample_asset_checker_window.png
--------------------------------------------------------------------------------
/Documents~/imgs/img_sample_asset_checker_new_settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SolarianZ/UnityAssetChecker/HEAD/Documents~/imgs/img_sample_asset_checker_new_settings.png
--------------------------------------------------------------------------------
/Editor/ResultTypeIconStyle.cs:
--------------------------------------------------------------------------------
1 | namespace GBG.AssetChecking.Editor
2 | {
3 | public enum ResultTypeIconStyle
4 | {
5 | Style1,
6 | Style2,
7 | Style3
8 | }
9 | }
--------------------------------------------------------------------------------
/LICENSE.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: dc8b8e95ae4f924449aad800698edda2
3 | DefaultImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/README.md.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 13763f616ab3acc4b8d1a6496e0a2d34
3 | TextScriptImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/README_CN.md.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 2fa4e2c17401a6045bd905ff1122df70
3 | TextScriptImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/package.json.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 275df7006fb1a2b4ca147b04cb7556f3
3 | PackageManifestImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/Editor.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 7c95e7e38146dd44dbaf8e1f4bb095fd
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Editor/BuiltinProviders.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: a76a689caa4f29247bc5b15545a853f9
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Editor/GBG.AssetChecker.Editor.asmdef.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 4e6095db9a4acdf4f855f84f0d925ab5
3 | AssemblyDefinitionImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/Editor/AssetChecker.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 3830f4453dd96d74a93b69143c2287ae
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Editor/AssetProvider.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 4454c208aec4b124e9117668f3446ea2
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Editor/AssetCheckResult.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 4013ed18f34da434495674693d9856cc
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Editor/CheckResultStats.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: b2ccdef89613ef74f9d6f2111a86f400
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Editor/CheckResultType.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: f2d0b826323f02d4c816c938d1691238
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Editor/CustomViewProvider.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: eed1fb3b3ff7bb44e8ee5d3e93c407b4
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Editor/ResultTypeIconStyle.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 9e9f28f4dcbc1af4d8f9efd5f15809cf
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Editor/AssetCheckerLocalCache.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 43a4fed22883b6448bec5536f6241c73
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Editor/CheckResultDetailsView.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 6edeea117a5417f4389bc56d0b737033
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Editor/CheckResultEntryView.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 0f9ab8f9c26d7b74b97385064b60e2f3
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Editor/BuiltinProviders/ExplicitAssetProvider.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 0e77bbfbcbef8bb498da62d6019930aa
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Editor/BuiltinProviders/SelectionAssetProvider.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 9d8f8eca555cd0c4ead45354cba1f534
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Editor/BuiltinProviders/TextSearchAssetProvider.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 925338c10dbb53e42bf73eeb7c1e14cb
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Editor/AssetProvider.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using UnityEngine;
3 | using UObject = UnityEngine.Object;
4 |
5 | namespace GBG.AssetChecking.Editor
6 | {
7 | public abstract class AssetProvider : ScriptableObject
8 | {
9 | ///
10 | /// Obtain the assets to be checked.
11 | ///
12 | ///
13 | public abstract IReadOnlyList GetAssets();
14 | }
15 | }
--------------------------------------------------------------------------------
/Editor/AssetCheckerWindow.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 3ecd11746ce735042a0dbf5cb30a651a
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences:
7 | - m_ViewDataDictionary: {instanceID: 0}
8 | - _mainVisualTreeAsset: {fileID: 9197481963319205126, guid: 27e4c26865ba0624b968ef6e13d478df,
9 | type: 3}
10 | executionOrder: 0
11 | icon: {instanceID: 0}
12 | userData:
13 | assetBundleName:
14 | assetBundleVariant:
15 |
--------------------------------------------------------------------------------
/Editor/GBG.AssetChecker.Editor.asmdef:
--------------------------------------------------------------------------------
1 | {
2 | "name": "GBG.AssetChecker.Editor",
3 | "rootNamespace": "GBG.AssetChecker.Editor",
4 | "references": [],
5 | "includePlatforms": [
6 | "Editor"
7 | ],
8 | "excludePlatforms": [],
9 | "allowUnsafeCode": true,
10 | "overrideReferences": false,
11 | "precompiledReferences": [],
12 | "autoReferenced": true,
13 | "defineConstraints": [],
14 | "versionDefines": [],
15 | "noEngineReferences": false
16 | }
--------------------------------------------------------------------------------
/Editor/CustomViewProvider.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 | using UnityEngine.UIElements;
3 |
4 | namespace GBG.AssetChecking.Editor
5 | {
6 | public abstract class CustomDetailsView : VisualElement
7 | {
8 | public abstract string CustomViewId { get; }
9 |
10 |
11 | public abstract void Bind(AssetCheckResult checkResult);
12 | }
13 |
14 | public abstract class CustomViewProvider : ScriptableObject
15 | {
16 | public abstract CustomDetailsView GetDetailsView(string customViewId);
17 | }
18 | }
--------------------------------------------------------------------------------
/Editor/BuiltinProviders/ExplicitAssetProvider.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using UnityEngine;
4 | using UObject = UnityEngine.Object;
5 |
6 | namespace GBG.AssetChecking.Editor
7 | {
8 | [CreateAssetMenu(menuName = "Bamboo/Asset Checker/Explicit Asset Provider")]
9 | public class ExplicitAssetProvider : AssetProvider
10 | {
11 | public UObject[] assets = Array.Empty();
12 |
13 |
14 | public override IReadOnlyList GetAssets()
15 | {
16 | return assets;
17 | }
18 | }
19 | }
--------------------------------------------------------------------------------
/Editor/BuiltinProviders/SelectionAssetProvider.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using UnityEditor;
3 | using UnityEngine;
4 | using UObject = UnityEngine.Object;
5 |
6 | namespace GBG.AssetChecking.Editor
7 | {
8 | [CreateAssetMenu(menuName = "Bamboo/Asset Checker/Selection Asset Provider")]
9 | public class SelectionAssetProvider : AssetProvider
10 | {
11 | public SelectionMode selectionModes = SelectionMode.Unfiltered;
12 |
13 |
14 | public override IReadOnlyList GetAssets()
15 | {
16 | UObject[] objects = Selection.GetFiltered(selectionModes);
17 | return objects;
18 | }
19 | }
20 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "com.greenbamboogames.assetchecker",
3 | "version": "1.2.0",
4 | "displayName": "Asset Checker!",
5 | "description": "Easy to use and extensible asset checking tool.",
6 | "unity": "2020.3",
7 | "documentationUrl": "https://github.com/SolarianZ/UnityAssetChecker",
8 | "changelogUrl": "https://github.com/SolarianZ/UnityAssetChecker/releases",
9 | "licensesUrl": "https://github.com/SolarianZ/UnityAssetChecker/blob/main/LICENSE",
10 | "keywords": [
11 | "Asset",
12 | "Check",
13 | "Validate"
14 | ],
15 | "author": {
16 | "name": "ZQY",
17 | "email": "vdergow@hotmail.com",
18 | "url": ""
19 | },
20 | "type": "tool",
21 | "hideInEditor": false
22 | }
--------------------------------------------------------------------------------
/Editor/AssetCheckResult.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using UnityEngine;
3 | using UObject = UnityEngine.Object;
4 |
5 | namespace GBG.AssetChecking.Editor
6 | {
7 | [Serializable]
8 | public class AssetCheckResult
9 | {
10 | public CheckResultType type = CheckResultType.Exception;
11 | public string[] categories;
12 | public string title;
13 | public string details;
14 | public UObject asset;
15 | public AssetChecker checker;
16 | public bool repairable;
17 | [SerializeReference]
18 | public AssetCheckResultCustomData customData;
19 | public string customViewId;
20 | }
21 |
22 | [Serializable]
23 | public abstract class AssetCheckResultCustomData
24 | {
25 |
26 | }
27 | }
--------------------------------------------------------------------------------
/Editor/AssetCheckerSettings.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using UnityEngine;
3 |
4 | #if ODIN_INSPECTOR
5 | using Sirenix.OdinInspector;
6 | #endif
7 |
8 | namespace GBG.AssetChecking.Editor
9 | {
10 | [CreateAssetMenu(menuName = "Bamboo/Asset Checker/Asset Checker Settings")]
11 | public class AssetCheckerSettings : ScriptableObject
12 | {
13 | #nullable enable
14 | [Tooltip("Provides custom views. Can be null.")]
15 | public CustomViewProvider? customViewProvider;
16 | #nullable disable
17 | #if ODIN_INSPECTOR
18 | [Required]
19 | #endif
20 | [Tooltip("Provides assets for checking. Required.")]
21 | public AssetProvider assetProvider;
22 | #if ODIN_INSPECTOR
23 | [Required]
24 | [RequiredListLength(1, null)]
25 | #endif
26 | [Tooltip("Provides checkers for checking assets. Required.")]
27 | public AssetChecker[] assetCheckers = Array.Empty();
28 | }
29 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 Qiuyu ZHANG
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # This .gitignore file should be placed at the root of your Unity project directory
2 | #
3 | # Get latest from https://github.com/github/gitignore/blob/master/Unity.gitignore
4 | #
5 | /[Ll]ibrary/
6 | /[Tt]emp/
7 | /[Oo]bj/
8 | /[Bb]uild/
9 | /[Bb]uilds/
10 | /[Ll]ogs/
11 | /[Mm]emoryCaptures/
12 |
13 | # Asset meta data should only be ignored when the corresponding asset is also ignored
14 | !/[Aa]ssets/**/*.meta
15 |
16 | # Uncomment this line if you wish to ignore the asset store tools plugin
17 | # /[Aa]ssets/AssetStoreTools*
18 |
19 | # Autogenerated Jetbrains Rider plugin
20 | [Aa]ssets/Plugins/Editor/JetBrains*
21 |
22 | # Visual Studio cache directory
23 | .vs/
24 |
25 | # Gradle cache directory
26 | .gradle/
27 |
28 | # Autogenerated VS/MD/Consulo solution and project files
29 | ExportedObj/
30 | .consulo/
31 | *.csproj
32 | *.unityproj
33 | *.sln
34 | *.suo
35 | *.tmp
36 | *.user
37 | *.userprefs
38 | *.pidb
39 | *.booproj
40 | *.svd
41 | *.pdb
42 | *.mdb
43 | *.opendb
44 | *.VC.db
45 |
46 | # Unity3D generated meta files
47 | *.pidb.meta
48 | *.pdb.meta
49 | *.mdb.meta
50 |
51 | # Unity3D generated file on crash reports
52 | sysinfo.txt
53 |
54 | # Builds
55 | *.apk
56 | *.unitypackage
57 |
58 | # Crashlytics generated file
59 | crashlytics-build.properties
60 |
61 |
--------------------------------------------------------------------------------
/Editor/CheckResultStats.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace GBG.AssetChecking.Editor
4 | {
5 | [Serializable]
6 | public class CheckResultStats : ICloneable
7 | {
8 | public int error;
9 | public int warning;
10 | public int notImportant;
11 | public int allPass;
12 | public int exception;
13 | public int nullResult;
14 |
15 |
16 | public int GetTotal(bool includeNullResult)
17 | {
18 | int total = error + warning + notImportant + allPass + exception;
19 | if (includeNullResult)
20 | {
21 | total += nullResult;
22 | }
23 | return total;
24 | }
25 |
26 | public void Reset()
27 | {
28 | error = 0;
29 | warning = 0;
30 | notImportant = 0;
31 | allPass = 0;
32 | exception = 0;
33 | nullResult = 0;
34 | }
35 |
36 | public object Clone()
37 | {
38 | return new CheckResultStats
39 | {
40 | error = error,
41 | warning = warning,
42 | notImportant = notImportant,
43 | allPass = allPass,
44 | exception = exception,
45 | nullResult = nullResult,
46 | };
47 | }
48 | }
49 | }
--------------------------------------------------------------------------------
/Editor/BuiltinProviders/TextSearchAssetProvider.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Text.RegularExpressions;
3 | using UnityEditor;
4 | using UnityEngine;
5 | using UDebug = UnityEngine.Debug;
6 | using UObject = UnityEngine.Object;
7 |
8 | namespace GBG.AssetChecking.Editor
9 | {
10 | ///
11 | /// Search the asset database using the search filter string.
12 | ///
13 | ///
14 | [HelpURL("https://docs.unity3d.com/ScriptReference/AssetDatabase.FindAssets.html")]
15 | [CreateAssetMenu(menuName = "Bamboo/Asset Checker/Text Search Asset Provider")]
16 | public class TextSearchAssetProvider : AssetProvider
17 | {
18 | [Tooltip("The filter string can provide names, labels or types (class names). Refer to AssetDatabase.FindAssets.")]
19 | public string filter;
20 | [Tooltip("If not empty, the search results will only include assets whose paths match this regular expression.")]
21 | public string includePattern;
22 | [Tooltip("If not empty, the search results will not include assets whose paths match this regular expression.")]
23 | public string excludePattern;
24 | [Tooltip("The folders where the search will start. Refer to AssetDatabase.FindAssets.")]
25 | public string[] searchInFolders = new string[] { "Assets" };
26 | [Tooltip("If checked, the search results will not include DefaultAssets (folders, unsupported file types, etc.).")]
27 | public bool ignoreDefaultAssets;
28 |
29 |
30 | public override IReadOnlyList GetAssets()
31 | {
32 | string[] guids = AssetDatabase.FindAssets(filter, searchInFolders);
33 | List objects = new List(guids.Length);
34 | Regex includeRegex = string.IsNullOrEmpty(includePattern) ? null : new Regex(includePattern);
35 | Regex excludeRegex = string.IsNullOrEmpty(excludePattern) ? null : new Regex(excludePattern);
36 | foreach (string guid in guids)
37 | {
38 | string path = AssetDatabase.GUIDToAssetPath(guid);
39 | if (includeRegex != null && !includeRegex.IsMatch(path))
40 | {
41 | continue;
42 | }
43 |
44 | if (excludeRegex != null && includeRegex.IsMatch(path))
45 | {
46 | continue;
47 | }
48 |
49 | UObject asset = AssetDatabase.LoadAssetAtPath(path);
50 | if (ignoreDefaultAssets && asset is DefaultAsset)
51 | {
52 | continue;
53 | }
54 |
55 | if (!asset)
56 | {
57 | UDebug.LogError($"[{AssetChecker.LogTag}] The asset exists but cannot be loaded: {path}.", asset);
58 | }
59 |
60 | objects.Add(asset);
61 | }
62 | return objects;
63 | }
64 | }
65 | }
--------------------------------------------------------------------------------
/Editor/CheckResultEntryView.cs:
--------------------------------------------------------------------------------
1 | using UnityEditor;
2 | using UnityEngine;
3 | using UnityEngine.UIElements;
4 |
5 | namespace GBG.AssetChecking.Editor
6 | {
7 | public class CheckResultEntryView : VisualElement
8 | {
9 | private readonly Image _typeImage;
10 | private readonly Image _assetImage;
11 | private readonly Label _label;
12 | private readonly Image _repairableImage;
13 |
14 |
15 | public CheckResultEntryView()
16 | {
17 | style.flexDirection = FlexDirection.Row;
18 |
19 | _typeImage = new Image
20 | {
21 | name = "TypeImage",
22 | style =
23 | {
24 | width = 20,
25 | minWidth = 20,
26 | maxWidth = 20,
27 | height = 20,
28 | minHeight = 20,
29 | maxHeight = 20,
30 | alignSelf = Align.Center,
31 | }
32 | };
33 | Add(_typeImage);
34 |
35 | _assetImage = new Image
36 | {
37 | name = "AssetImage",
38 | style =
39 | {
40 | width = 20,
41 | minWidth = 20,
42 | maxWidth = 20,
43 | height = 20,
44 | minHeight = 20,
45 | maxHeight = 20,
46 | alignSelf = Align.Center,
47 | }
48 | };
49 | Add(_assetImage);
50 |
51 | _label = new Label
52 | {
53 | name = "Label",
54 | style =
55 | {
56 | flexGrow = 1,
57 | flexShrink = 1,
58 | overflow = Overflow.Hidden,
59 | unityTextAlign = TextAnchor.MiddleLeft,
60 | }
61 | };
62 | Add(_label);
63 |
64 | _repairableImage = new Image
65 | {
66 | name = "RepairableImage",
67 | tooltip = "Repairable",
68 | image = EditorGUIUtility.isProSkin
69 | ? EditorGUIUtility.IconContent("d_CustomTool@2x").image
70 | : EditorGUIUtility.IconContent("CustomTool@2x").image,
71 | style =
72 | {
73 | width = 20,
74 | minWidth = 20,
75 | maxWidth = 20,
76 | height = 20,
77 | minHeight = 20,
78 | maxHeight = 20,
79 | alignSelf = Align.Center,
80 | }
81 | };
82 | Add(_repairableImage);
83 | }
84 |
85 | public void Bind(AssetCheckResult result)
86 | {
87 | ResultTypeIconStyle iconStyle = AssetCheckerLocalCache.instance.GetCheckResultTypeIconStyle();
88 | _typeImage.image = result.type.GetResultTypeIcon(iconStyle);
89 | if (AssetCheckerLocalCache.instance.GetShowResultEntryAssetIcon())
90 | {
91 | _assetImage.style.display = DisplayStyle.Flex;
92 | _assetImage.image = result.asset != null
93 | ? AssetPreview.GetMiniThumbnail(result.asset)
94 | : null;
95 | }
96 | else
97 | {
98 | _assetImage.style.display = DisplayStyle.None;
99 | }
100 | _label.text = result.title;
101 | _repairableImage.style.display = result.repairable
102 | ? DisplayStyle.Flex
103 | : DisplayStyle.None;
104 | }
105 | }
106 | }
--------------------------------------------------------------------------------
/Editor/AssetCheckerLocalCache.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using UnityEditor;
5 | using UnityEngine;
6 |
7 | namespace GBG.AssetChecking.Editor
8 | {
9 | [FilePath("Library/com.greenbamboogames.assetchecker/LocalCache.asset",
10 | FilePathAttribute.Location.ProjectFolder)]
11 | internal class AssetCheckerLocalCache : ScriptableSingleton
12 | {
13 | public const string AllCategories = "All Categories";
14 | public const string Repairable = "Repairable";
15 |
16 | [SerializeField]
17 | private AssetCheckerSettings _settingsAsset;
18 | [SerializeField]
19 | private CheckResultStats _checkResultStats = new CheckResultStats();
20 | [SerializeField]
21 | private AssetCheckResult[] _checkResults = Array.Empty();
22 | [SerializeField]
23 | private CheckResultTypes _resultTypeFilter =
24 | #if UNITY_2022_3_OR_NEWER
25 | CheckResultTypes.AllTypes;
26 | #else
27 | (CheckResultTypes)~0U;
28 | #endif
29 | [SerializeField]
30 | private string _resultCategoryFilter = AllCategories;
31 | [SerializeField]
32 | private ResultTypeIconStyle _resultIconStyle = ResultTypeIconStyle.Style2;
33 | [SerializeField]
34 | private bool _showResultEntryAssetIcon = true;
35 |
36 | public CustomViewProvider InstantCustomViewProvider { get; set; }
37 |
38 |
39 | public AssetCheckerSettings GetSettingsAsset()
40 | {
41 | return _settingsAsset;
42 | }
43 |
44 | public void SetSettingsAsset(AssetCheckerSettings settings)
45 | {
46 | _settingsAsset = settings;
47 | Save(true);
48 | }
49 |
50 | public AssetCheckResult[] GetCheckResults()
51 | {
52 | return _checkResults.ToArray();
53 | }
54 |
55 | public void SetCheckResults(IEnumerable checkResults)
56 | {
57 | _checkResults = checkResults?.ToArray() ?? Array.Empty();
58 | Save(true);
59 | }
60 |
61 | public CheckResultTypes GetCheckResultTypeFilter()
62 | {
63 | return _resultTypeFilter;
64 | }
65 |
66 | public void SetCheckResultTypeFilter(CheckResultTypes types)
67 | {
68 | _resultTypeFilter = types;
69 | Save(true);
70 | }
71 |
72 | public string GetCheckResultCategoryFilter()
73 | {
74 | return _resultCategoryFilter;
75 | }
76 |
77 | public void SetCheckResultCategoryFilter(string category)
78 | {
79 | _resultCategoryFilter = string.IsNullOrWhiteSpace(category)
80 | ? AllCategories
81 | : category.Trim();
82 | Save(true);
83 | }
84 |
85 | public CheckResultStats GetCheckResultStats()
86 | {
87 | CheckResultStats stats = (CheckResultStats)_checkResultStats.Clone();
88 | return stats;
89 | }
90 |
91 | public void SetCheckResultStats(CheckResultStats stats)
92 | {
93 | _checkResultStats = stats == null
94 | ? new CheckResultStats()
95 | : (CheckResultStats)stats.Clone();
96 | Save(true);
97 | }
98 |
99 | public ResultTypeIconStyle GetCheckResultTypeIconStyle()
100 | {
101 | return _resultIconStyle;
102 | }
103 |
104 | public void SetCheckResultIconStyle(ResultTypeIconStyle iconStyle)
105 | {
106 | _resultIconStyle = iconStyle;
107 | Save(true);
108 | }
109 |
110 | public bool GetShowResultEntryAssetIcon()
111 | {
112 | return _showResultEntryAssetIcon;
113 | }
114 |
115 | public void SetShowResultEntryAssetIcon(bool showResultEntryAssetIcon)
116 | {
117 | _showResultEntryAssetIcon = showResultEntryAssetIcon;
118 | Save(true);
119 | }
120 | }
121 | }
--------------------------------------------------------------------------------
/Editor/CheckResultType.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using UnityEditor;
3 | using UnityEngine;
4 |
5 | namespace GBG.AssetChecking.Editor
6 | {
7 | public enum CheckResultType : uint
8 | {
9 | AllPass = 1U << 0,
10 | NotImportant = 1U << 1,
11 | Warning = 1U << 2,
12 | Error = 1U << 3,
13 | Exception = 1U << 4,
14 | }
15 |
16 | [Flags]
17 | public enum CheckResultTypes : uint
18 | {
19 | #if UNITY_2022_3_OR_NEWER
20 | None = 0,
21 | AllTypes = ~0U,
22 | #endif
23 |
24 | // Sync with CheckResultType
25 | AllPass = CheckResultType.AllPass,
26 | NotImportant = CheckResultType.NotImportant,
27 | Warning = CheckResultType.Warning,
28 | Error = CheckResultType.Error,
29 | Exception = CheckResultType.Exception,
30 | }
31 |
32 | public static class CheckResultTypeHelper
33 | {
34 | public static Texture GetResultTypeIcon(this CheckResultType resultType, ResultTypeIconStyle iconStyle)
35 | {
36 | switch (resultType)
37 | {
38 | case CheckResultType.AllPass:
39 | switch (iconStyle)
40 | {
41 | case ResultTypeIconStyle.Style1:
42 | return EditorGUIUtility.IconContent("sv_icon_dot3_pix16_gizmo").image;
43 | case ResultTypeIconStyle.Style2:
44 | return EditorGUIUtility.IconContent("d_winbtn_mac_max@2x").image;
45 | case ResultTypeIconStyle.Style3:
46 | return EditorGUIUtility.IconContent("d_greenLight").image;
47 | default:
48 | throw new ArgumentOutOfRangeException(nameof(iconStyle), iconStyle, null);
49 | }
50 | case CheckResultType.NotImportant:
51 | switch (iconStyle)
52 | {
53 | case ResultTypeIconStyle.Style1:
54 | return EditorGUIUtility.IconContent("sv_icon_dot0_pix16_gizmo").image;
55 | case ResultTypeIconStyle.Style2:
56 | return EditorGUIUtility.IconContent("sv_icon_dot0_pix16_gizmo").image;
57 | case ResultTypeIconStyle.Style3:
58 | return EditorGUIUtility.IconContent("sv_icon_dot0_pix16_gizmo").image;
59 | default:
60 | throw new ArgumentOutOfRangeException(nameof(iconStyle), iconStyle, null);
61 | }
62 | case CheckResultType.Warning:
63 | switch (iconStyle)
64 | {
65 | case ResultTypeIconStyle.Style1:
66 | return EditorGUIUtility.IconContent("sv_icon_dot5_pix16_gizmo").image;
67 | case ResultTypeIconStyle.Style2:
68 | return EditorGUIUtility.IconContent("d_winbtn_mac_min@2x").image;
69 | case ResultTypeIconStyle.Style3:
70 | return EditorGUIUtility.IconContent("d_orangeLight").image;
71 | default:
72 | throw new ArgumentOutOfRangeException(nameof(iconStyle), iconStyle, null);
73 | }
74 | case CheckResultType.Error:
75 | switch (iconStyle)
76 | {
77 | case ResultTypeIconStyle.Style1:
78 | return EditorGUIUtility.IconContent("sv_icon_dot6_pix16_gizmo").image;
79 | case ResultTypeIconStyle.Style2:
80 | return EditorGUIUtility.IconContent("d_winbtn_mac_close@2x").image;
81 | case ResultTypeIconStyle.Style3:
82 | return EditorGUIUtility.IconContent("d_redLight").image;
83 | default:
84 | throw new ArgumentOutOfRangeException(nameof(iconStyle), iconStyle, null);
85 | }
86 | case CheckResultType.Exception:
87 | switch (iconStyle)
88 | {
89 | case ResultTypeIconStyle.Style1:
90 | return EditorGUIUtility.IconContent("sv_icon_dot7_pix16_gizmo").image;
91 | case ResultTypeIconStyle.Style2:
92 | return EditorGUIUtility.IconContent("d_winbtn_mac_close_a@2x").image;
93 | case ResultTypeIconStyle.Style3:
94 | return EditorGUIUtility.IconContent("Error@2x").image;
95 | default:
96 | throw new ArgumentOutOfRangeException(nameof(iconStyle), iconStyle, null);
97 | }
98 | default:
99 | throw new ArgumentOutOfRangeException(nameof(resultType), resultType, null);
100 | }
101 | }
102 |
103 | public static Color GetResultTypeBorderColor(this CheckResultType resultType)
104 | {
105 | switch (resultType)
106 | {
107 | case CheckResultType.AllPass:
108 | return new Color(0 / 255f, 190 / 255f, 0 / 255f, 1.0f);
109 | case CheckResultType.NotImportant:
110 | return new Color(229 / 255f, 229 / 255f, 229 / 255f, 1.0f);
111 | case CheckResultType.Warning:
112 | return new Color(255 / 255f, 200 / 255f, 0 / 255f, 1.0f);
113 | case CheckResultType.Error:
114 | return new Color(255 / 255f, 0 / 255f, 0 / 255f, 1.0f);
115 | case CheckResultType.Exception:
116 | return new Color(150 / 255f, 0 / 255f, 0 / 255f, 1.0f);
117 | default:
118 | throw new ArgumentOutOfRangeException(nameof(resultType), resultType, null);
119 | }
120 | }
121 | }
122 | }
--------------------------------------------------------------------------------
/Editor/AssetChecker.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using UnityEditor;
4 | using UnityEngine;
5 | using UDebug = UnityEngine.Debug;
6 | using UObject = UnityEngine.Object;
7 |
8 | namespace GBG.AssetChecking.Editor
9 | {
10 | public enum ExecutionResult
11 | {
12 | Success,
13 | Failure,
14 | NoAssets,
15 | }
16 |
17 | public abstract class AssetChecker : ScriptableObject
18 | {
19 | ///
20 | /// Execute the asset checking process.
21 | ///
22 | /// The asset to be checked.
23 | /// Check result. Can be null(meaning there are no issues).
24 | public abstract AssetCheckResult CheckAsset(UObject asset);
25 |
26 | ///
27 | /// Attempt to repair the issues with the assets.
28 | ///
29 | /// Repair result. Can be null(meaning there are no issues).
30 | /// Whether all issues have been repaired.
31 | public abstract void RepairAsset(AssetCheckResult checkResult, out bool allIssuesRepaired);
32 |
33 |
34 | public const string CategoryName_Exception = "Exception";
35 | internal protected const string LogTag = "AssetChecker";
36 |
37 | ///
38 | /// Launch the asset checking process.
39 | ///
40 | /// Provides the assets to be checked.
41 | /// The list of checkers that operate on the assets.
42 | /// The results of the checks.
43 | /// The count of null results returned by checkers (null results are considered as passed checks).
44 | /// The log context (clicking on a log entry in the console will ping this object).
45 | /// Specifies whether to allow displaying popup messages.
46 | /// The execution result.
47 | public static ExecutionResult Execute(AssetProvider assetProvider,
48 | IReadOnlyList assetCheckers,
49 | List checkResults, out int nullResultCount,
50 | UObject logContext = null, bool allowDisplayDialog = true)
51 | {
52 | checkResults?.Clear();
53 | nullResultCount = 0;
54 |
55 | if (!assetProvider)
56 | {
57 | string errorMessage = $"Asset checker execution failed. Argument '{nameof(assetProvider)}' is null.";
58 | UDebug.LogError($"[{LogTag}] {errorMessage}", logContext);
59 | if (allowDisplayDialog)
60 | {
61 | EditorUtility.DisplayDialog("Error", errorMessage, "Ok");
62 | }
63 | return ExecutionResult.Failure;
64 | }
65 |
66 | if (assetCheckers == null || assetCheckers.Count == 0)
67 | {
68 | string errorMessage = $"Asset checker execution failed. Argument '{nameof(assetCheckers)}' is null or empty.";
69 | if (allowDisplayDialog)
70 | {
71 | UDebug.LogError($"[{LogTag}] {errorMessage}", logContext);
72 | }
73 | EditorUtility.DisplayDialog("Error", errorMessage, "Ok");
74 | return ExecutionResult.Failure;
75 | }
76 |
77 | if (checkResults == null)
78 | {
79 | string errorMessage = $"Asset checker execution failed. Argument '{nameof(checkResults)}' is null.";
80 | if (allowDisplayDialog)
81 | {
82 | UDebug.LogError($"[{LogTag}] {errorMessage}", logContext);
83 | }
84 | EditorUtility.DisplayDialog("Error", errorMessage, "Ok");
85 | return ExecutionResult.Failure;
86 | }
87 |
88 | IReadOnlyList assets = assetProvider.GetAssets();
89 | if (assets == null || assets.Count == 0)
90 | {
91 | string errorMessage = "Asset checker execution aborted. No assets were provided for check.";
92 | UDebug.LogWarning($"[{LogTag}] {errorMessage}", logContext);
93 | if (allowDisplayDialog)
94 | {
95 | EditorUtility.DisplayDialog("Warning", errorMessage, "Ok");
96 | }
97 | return ExecutionResult.NoAssets;
98 | }
99 |
100 | bool hasNullChecker = false;
101 | for (int i = 0; i < assets.Count; i++)
102 | {
103 | UObject asset = assets[i];
104 | for (int j = 0; j < assetCheckers.Count; j++)
105 | {
106 | AssetChecker checker = assetCheckers[j];
107 | if (!checker)
108 | {
109 | hasNullChecker = true;
110 | continue;
111 | }
112 |
113 | try
114 | {
115 | AssetCheckResult result = checker.CheckAsset(asset);
116 | if (result != null)
117 | {
118 | checkResults.Add(result);
119 | }
120 | else
121 | {
122 | nullResultCount++;
123 | }
124 | }
125 | catch (Exception e)
126 | {
127 | AssetCheckResult result = new AssetCheckResult
128 | {
129 | type = CheckResultType.Exception,
130 | categories = new string[] { CategoryName_Exception },
131 | title = e.GetType().Name,
132 | details = e.Message,
133 | asset = asset,
134 | checker = checker,
135 | repairable = false,
136 | customData = null,
137 | customViewId = null,
138 | };
139 | checkResults.Add(result);
140 | }
141 | }
142 | }
143 |
144 | if (hasNullChecker)
145 | {
146 | string errorMessage = $"Null items found in the argument '{nameof(assetCheckers)}', please check.";
147 | UDebug.LogError($"[{LogTag}] {errorMessage}", logContext);
148 | if (allowDisplayDialog)
149 | {
150 | EditorUtility.DisplayDialog("Error", errorMessage, "Ok");
151 | }
152 | }
153 |
154 | return ExecutionResult.Success;
155 | }
156 | }
157 | }
--------------------------------------------------------------------------------
/README_CN.md:
--------------------------------------------------------------------------------
1 | # Unity资产检查工具
2 |
3 | 易用且可扩展的资产检查工具。
4 |
5 | 
6 |
7 | [English](./README.md)
8 |
9 | ## 功能
10 |
11 | - 支持多套检查配置
12 | - 自定义要检查的资产范围
13 | - 自定义检查方式
14 | - 对资产顺序执行多个检查流程
15 | - 按结果类型筛选检查结果
16 | - 按自定义分类筛选检查结果
17 | - 对检查结果执行重新检查
18 | - 对检查结果尝试执行修复
19 | - 为检查结果创建自定义详细信息UI
20 | - 在重新打开检查器时,恢复上次检查的结果
21 | - 允许脱离UI,使用脚本发起检查流程
22 | - 支持多种检查结果UI样式
23 |
24 | ## 支持的Unity版本
25 |
26 | Unity 2020.3 或更新版本。
27 |
28 | 在Unity 2022.3之前的版本中,部分UI交互功能有所减弱,但不影响功能。
29 |
30 | ## 安装
31 |
32 | [](https://openupm.com/packages/com.greenbamboogames.assetchecker/)
33 |
34 | 从 [OpenUPM](https://openupm.com/packages/com.greenbamboogames.assetchecker) 安装,或者直接将此仓库克隆到项目的Packages文件夹下。
35 |
36 | ## 如何使用
37 |
38 | ### 创建Asset Provider资产
39 |
40 | Asset Provider是 `ScriptableObject` 的子类型,用于向Asset Checker提供要进行检查的资产。
41 |
42 | 首先,在项目中添加一个类型,继承 `AssetProvider` 类型,实现 `GetAssets` 方法,该方法返回 `IReadOnlyList` 。Asset Checker将会检查返回结果中的资产。
43 |
44 | 然后创建该类型的Asset Provider资产,稍后需要将该Asset Provider资产设置到配置资产中。
45 |
46 | 示例:
47 |
48 | ```csharp
49 | using GBG.AssetChecker.Editor.AssetChecker;
50 | using System.Collections.Generic;
51 | using UnityEngine;
52 |
53 | [CreateAssetMenu(menuName = "Tests/My Asset Provider")]
54 | public class MyAssetProvider : AssetProvider
55 | {
56 | public override IReadOnlyList