update libs

This commit is contained in:
Kirill Chikalin
2025-02-13 17:48:12 +03:00
parent e17e7c2786
commit 275dc598c7
816 changed files with 22479 additions and 10792 deletions

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: ecfb23f95f16d2347a4063411aad8063
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,64 @@
using AssetStoreTools.Validator.Data;
using AssetStoreTools.Validator.Services.Validation;
using AssetStoreTools.Validator.TestDefinitions;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityObject = UnityEngine.Object;
namespace AssetStoreTools.Validator.TestMethods
{
internal class CheckAnimationClips : ITestScript
{
private static readonly string[] InvalidNames = new[] { "Take 001" };
private GenericTestConfig _config;
private IAssetUtilityService _assetUtility;
public CheckAnimationClips(GenericTestConfig config, IAssetUtilityService assetUtility)
{
_config = config;
_assetUtility = assetUtility;
}
public TestResult Run()
{
var result = new TestResult() { Status = TestResultStatus.Undefined };
var badModels = new Dictionary<UnityObject, List<UnityObject>>();
var models = _assetUtility.GetObjectsFromAssets<UnityObject>(_config.ValidationPaths, AssetType.Model);
foreach (var model in models)
{
var badClips = new List<UnityObject>();
var clips = AssetDatabase.LoadAllAssetsAtPath(_assetUtility.ObjectToAssetPath(model));
foreach (var clip in clips)
{
if (InvalidNames.Any(x => x.ToLower().Equals(clip.name.ToLower())))
{
badClips.Add(clip);
}
}
if (badClips.Count > 0)
badModels.Add(model, badClips);
}
if (badModels.Count > 0)
{
result.Status = TestResultStatus.VariableSeverityIssue;
result.AddMessage("The following models have animation clips with invalid names. Animation clip names should be unique and reflective of the animation itself");
foreach (var kvp in badModels)
{
result.AddMessage(_assetUtility.ObjectToAssetPath(kvp.Key), null, kvp.Value.ToArray());
}
}
else
{
result.AddMessage("No animation clips with invalid names were found!");
result.Status = TestResultStatus.Pass;
}
return result;
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 7a28985886f182c4bacc89a44777c742
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 115
packageName: Asset Store Publishing Tools
packageVersion: 12.0.1
assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckAnimationClips.cs
uploadId: 724584

View File

@@ -0,0 +1,128 @@
using AssetStoreTools.Validator.Data;
using AssetStoreTools.Validator.Services.Validation;
using AssetStoreTools.Validator.TestDefinitions;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
namespace AssetStoreTools.Validator.TestMethods
{
internal class CheckAudioClipping : ITestScript
{
private GenericTestConfig _config;
private IAssetUtilityService _assetUtility;
public CheckAudioClipping(GenericTestConfig config, IAssetUtilityService assetUtility)
{
_config = config;
_assetUtility = assetUtility;
}
public TestResult Run()
{
// How many peaks above threshold are required for Audio Clips to be considered clipping
const int TOLERANCE = 2;
// Min. amount of consecutive samples above threshold required for peak detection
const int PEAK_STEPS = 1;
// Clipping threshold. More lenient here than Submission Guidelines (-0.3db) due to the problematic nature of
// correctly determining how sensitive the audio clipping flagging should be, as well as to account for any
// distortion introduced when AudioClips are compresssed after importing to Unity.
const float THRESHOLD = -0.05f;
// Samples for 16-bit audio files
const float S16b = 32767f;
float clippingThreshold = (S16b - (S16b / (2 * Mathf.Log10(1 / S16b)) * THRESHOLD)) / S16b;
TestResult result = new TestResult();
var clippingAudioClips = new Dictionary<AudioClip, string>();
var losslessAudioClips = _assetUtility.GetObjectsFromAssets(_config.ValidationPaths, AssetType.NonLossyAudio).Select(x => x as AudioClip).ToList();
foreach (var clip in losslessAudioClips)
{
var path = AssetDatabase.GetAssetPath(clip.GetInstanceID());
if (IsClipping(clip, TOLERANCE, PEAK_STEPS, clippingThreshold))
clippingAudioClips.Add(clip, path);
}
var lossyAudioClips = _assetUtility.GetObjectsFromAssets(_config.ValidationPaths, AssetType.LossyAudio).Select(x => x as AudioClip).ToList();
foreach (var clip in lossyAudioClips)
{
var path = AssetDatabase.GetAssetPath(clip.GetInstanceID());
if (IsClipping(clip, TOLERANCE, PEAK_STEPS, clippingThreshold))
clippingAudioClips.Add(clip, path);
}
if (clippingAudioClips.Count > 0)
{
result.Status = TestResultStatus.VariableSeverityIssue;
result.AddMessage("The following AudioClips are clipping or are very close to 0db ceiling. Please ensure your exported audio files have at least 0.3db of headroom (should peak at no more than -0.3db):", null, clippingAudioClips.Select(x => x.Key).ToArray());
}
else
{
result.Status = TestResultStatus.Pass;
result.AddMessage("No clipping audio files were detected.");
}
return result;
}
private bool IsClipping(AudioClip clip, int tolerance, int peakTolerance, float clippingThreshold)
{
if (DetectNumPeaksAboveThreshold(clip, peakTolerance, clippingThreshold) >= tolerance)
return true;
return false;
}
private int DetectNumPeaksAboveThreshold(AudioClip clip, int peakTolerance, float clippingThreshold)
{
float[] samples = new float[clip.samples * clip.channels];
var data = clip.GetData(samples, 0);
float[] samplesLeft = samples.Where((s, i) => i % 2 == 0).ToArray();
float[] samplesRight = samples.Where((s, i) => i % 2 == 1).ToArray();
int peaks = 0;
peaks = GetPeaksInChannel(samplesLeft, peakTolerance, clippingThreshold) +
GetPeaksInChannel(samplesRight, peakTolerance, clippingThreshold);
return peaks;
}
private int GetPeaksInChannel(float[] samples, int peakTolerance, float clippingThreshold)
{
int peaks = 0;
bool evalPeak = false;
int peakSteps = 0;
int step = 0;
while (step < samples.Length)
{
if (Mathf.Abs(samples[step]) >= clippingThreshold && evalPeak)
{
peakSteps++;
}
if (Mathf.Abs(samples[step]) >= clippingThreshold && !evalPeak)
{
evalPeak = true;
peakSteps++;
}
if (Mathf.Abs(samples[step]) < clippingThreshold && evalPeak)
{
evalPeak = false;
if (peakSteps >= peakTolerance)
peaks++;
peakSteps = 0;
}
step++;
}
return peaks;
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: f604db0353da0cb46bb048f5cd37186f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 115
packageName: Asset Store Publishing Tools
packageVersion: 12.0.1
assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckAudioClipping.cs
uploadId: 724584

View File

@@ -0,0 +1,55 @@
using AssetStoreTools.Validator.Data;
using AssetStoreTools.Validator.Services.Validation;
using AssetStoreTools.Validator.TestDefinitions;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace AssetStoreTools.Validator.TestMethods
{
internal class CheckColliders : ITestScript
{
private GenericTestConfig _config;
private IAssetUtilityService _assetUtility;
private IMeshUtilityService _meshUtility;
public CheckColliders(GenericTestConfig config, IAssetUtilityService assetUtility, IMeshUtilityService meshUtility)
{
_config = config;
_assetUtility = assetUtility;
_meshUtility = meshUtility;
}
public TestResult Run()
{
var result = new TestResult() { Status = TestResultStatus.Undefined };
var prefabs = _assetUtility.GetObjectsFromAssets<GameObject>(_config.ValidationPaths, AssetType.Prefab);
var badPrefabs = new List<GameObject>();
foreach (var p in prefabs)
{
var meshes = _meshUtility.GetCustomMeshesInObject(p);
if (!p.isStatic || !meshes.Any())
continue;
var colliders = p.GetComponentsInChildren<Collider>(true);
if (!colliders.Any())
badPrefabs.Add(p);
}
if (badPrefabs.Count == 0)
{
result.Status = TestResultStatus.Pass;
result.AddMessage("All found prefabs have colliders!");
return result;
}
result.Status = TestResultStatus.VariableSeverityIssue;
result.AddMessage("The following prefabs contain meshes, but colliders were not found", null, badPrefabs.ToArray());
return result;
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 308b3d7b7a883b949a14f47cfd5c7ebe
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 115
packageName: Asset Store Publishing Tools
packageVersion: 12.0.1
assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckColliders.cs
uploadId: 724584

View File

@@ -0,0 +1,121 @@
using AssetStoreTools.Validator.Data;
using AssetStoreTools.Validator.Services.Validation;
using AssetStoreTools.Validator.TestDefinitions;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityObject = UnityEngine.Object;
namespace AssetStoreTools.Validator.TestMethods
{
internal class CheckCompressedFiles : ITestScript
{
private enum ArchiveResult
{
Allowed,
NotAllowed,
TarGzWithIssues,
ZipWithIssues
}
private GenericTestConfig _config;
private IAssetUtilityService _assetUtility;
private IFileSignatureUtilityService _fileSignatureUtility;
public CheckCompressedFiles(GenericTestConfig config, IAssetUtilityService assetUtility, IFileSignatureUtilityService fileSignatureUtility)
{
_config = config;
_assetUtility = assetUtility;
_fileSignatureUtility = fileSignatureUtility;
}
public TestResult Run()
{
var result = new TestResult() { Status = TestResultStatus.Undefined };
var checkedArchives = new Dictionary<UnityObject, ArchiveResult>();
// Retrieving assets via GetObjectsFromAssets() is insufficient because
// archives might be renamed and not use the expected extension
var allAssetPaths = _assetUtility.GetAssetPathsFromAssets(_config.ValidationPaths, AssetType.All);
foreach (var assetPath in allAssetPaths)
{
ArchiveType archiveType;
if ((archiveType = _fileSignatureUtility.GetArchiveType(assetPath)) == ArchiveType.None)
continue;
var archiveObj = _assetUtility.AssetPathToObject(assetPath);
switch (archiveType)
{
case ArchiveType.TarGz:
if (assetPath.ToLower().EndsWith(".unitypackage"))
checkedArchives.Add(archiveObj, ArchiveResult.Allowed);
else
checkedArchives.Add(archiveObj, ArchiveResult.TarGzWithIssues);
break;
case ArchiveType.Zip:
if (FileNameContainsKeyword(assetPath, "source") && assetPath.ToLower().EndsWith(".zip"))
checkedArchives.Add(archiveObj, ArchiveResult.Allowed);
else
checkedArchives.Add(archiveObj, ArchiveResult.ZipWithIssues);
break;
default:
checkedArchives.Add(archiveObj, ArchiveResult.NotAllowed);
break;
}
}
if (checkedArchives.Count == 0)
{
result.Status = TestResultStatus.Pass;
result.AddMessage("No archives were found in the package content!");
return result;
}
if (checkedArchives.Any(x => x.Value == ArchiveResult.Allowed))
{
result.Status = TestResultStatus.Warning;
result.AddMessage("The following archives of allowed format were found in the package content.\n" +
"Please make sure they adhere to the nested archive guidelines:", null,
checkedArchives.Where(x => x.Value == ArchiveResult.Allowed).Select(x => x.Key).ToArray());
}
if (checkedArchives.Any(x => x.Value == ArchiveResult.TarGzWithIssues))
{
result.Status = TestResultStatus.VariableSeverityIssue;
result.AddMessage("The following .gz archives were found in the package content.\n" +
"<22> Gz archives are only allowed in form of '.unitypackage' files", null,
checkedArchives.Where(x => x.Value == ArchiveResult.TarGzWithIssues).Select(x => x.Key).ToArray());
}
if (checkedArchives.Any(x => x.Value == ArchiveResult.ZipWithIssues))
{
result.Status = TestResultStatus.VariableSeverityIssue;
result.AddMessage("The following .zip archives were found in the package content.\n" +
"<22> Zip archives should contain the keyword 'source' in the file name", null,
checkedArchives.Where(x => x.Value == ArchiveResult.ZipWithIssues).Select(x => x.Key).ToArray());
}
if (checkedArchives.Any(x => x.Value == ArchiveResult.NotAllowed))
{
result.Status = TestResultStatus.VariableSeverityIssue;
result.AddMessage("The following archives are using formats that are not allowed:", null,
checkedArchives.Where(x => x.Value == ArchiveResult.NotAllowed).Select(x => x.Key).ToArray());
}
return result;
}
private bool FileNameContainsKeyword(string filePath, string keyword)
{
var fileInfo = new FileInfo(filePath);
if (!fileInfo.Exists)
return false;
return fileInfo.Name.Remove(fileInfo.Name.Length - fileInfo.Extension.Length).ToLower().Contains(keyword.ToLower());
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 84b23febe0d923842aef73b95da5f25b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 115
packageName: Asset Store Publishing Tools
packageVersion: 12.0.1
assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckCompressedFiles.cs
uploadId: 724584

View File

@@ -0,0 +1,46 @@
using AssetStoreTools.Validator.Data;
using AssetStoreTools.Validator.Services.Validation;
using AssetStoreTools.Validator.TestDefinitions;
using System.Collections.Generic;
using UnityEngine;
namespace AssetStoreTools.Validator.TestMethods
{
internal class CheckEmptyPrefabs : ITestScript
{
private GenericTestConfig _config;
private IAssetUtilityService _assetUtility;
public CheckEmptyPrefabs(GenericTestConfig config, IAssetUtilityService assetUtility)
{
_config = config;
_assetUtility = assetUtility;
}
public TestResult Run()
{
var result = new TestResult() { Status = TestResultStatus.Undefined };
var prefabs = _assetUtility.GetObjectsFromAssets<GameObject>(_config.ValidationPaths, AssetType.Prefab);
var badPrefabs = new List<GameObject>();
foreach (var p in prefabs)
{
if (p.GetComponents<Component>().Length == 1 && p.transform.childCount == 0)
badPrefabs.Add(p);
}
if (badPrefabs.Count == 0)
{
result.Status = TestResultStatus.Pass;
result.AddMessage("No empty prefabs were found!");
return result;
}
result.Status = TestResultStatus.VariableSeverityIssue;
result.AddMessage("The following prefabs are empty", null, badPrefabs.ToArray());
return result;
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 8055bed9373283e4793463b90b42f08f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 115
packageName: Asset Store Publishing Tools
packageVersion: 12.0.1
assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckEmptyPrefabs.cs
uploadId: 724584

View File

@@ -0,0 +1,153 @@
using AssetStoreTools.Validator.Data;
using AssetStoreTools.Validator.Services.Validation;
using AssetStoreTools.Validator.TestDefinitions;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEditor;
using UnityObject = UnityEngine.Object;
namespace AssetStoreTools.Validator.TestMethods
{
internal class CheckFileMenuNames : ITestScript
{
private GenericTestConfig _config;
private IAssetUtilityService _assetUtility;
private IScriptUtilityService _scriptUtility;
public CheckFileMenuNames(GenericTestConfig config, IAssetUtilityService assetUtility, IScriptUtilityService scriptUtility)
{
_config = config;
_assetUtility = assetUtility;
_scriptUtility = scriptUtility;
}
public TestResult Run()
{
var result = new TestResult() { Status = TestResultStatus.Undefined };
var bindingFlags = BindingFlags.Public | BindingFlags.NonPublic |
BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly;
#region Scripts
var scripts = _assetUtility.GetObjectsFromAssets<MonoScript>(_config.ValidationPaths, AssetType.MonoScript).ToArray();
var scriptTypes = _scriptUtility.GetTypesFromScriptAssets(scripts);
var affectedScripts = new Dictionary<MonoScript, List<string>>();
foreach (var kvp in scriptTypes)
{
var badMethods = new List<string>();
foreach (var type in kvp.Value)
{
foreach (var method in type.GetMethods(bindingFlags))
{
var attributes = method.GetCustomAttributes<MenuItem>().ToList();
if (attributes.Count == 0)
continue;
var badAttributes = attributes.Where(x => !IsValidMenuItem(x.menuItem)).ToList();
if (badAttributes.Count > 0)
badMethods.Add($"{string.Join("\n", badAttributes.Select(x => $"\'{x.menuItem}\'"))}\n(for method '{method.Name}')\n");
}
}
if (badMethods.Count > 0)
affectedScripts.Add(kvp.Key, badMethods);
}
#endregion
#region Precompiled Assemblies
var assemblies = _assetUtility.GetObjectsFromAssets(_config.ValidationPaths, AssetType.PrecompiledAssembly).ToArray();
var assemblyTypes = _scriptUtility.GetTypesFromAssemblies(assemblies);
var affectedAssemblies = new Dictionary<UnityObject, List<string>>();
foreach (var kvp in assemblyTypes)
{
var badMethods = new List<string>();
foreach (var type in kvp.Value)
{
foreach (var method in type.GetMethods(bindingFlags))
{
var attributes = method.GetCustomAttributes<MenuItem>().ToList();
if (attributes.Count == 0)
continue;
var badAttributes = attributes.Where(x => !IsValidMenuItem(x.menuItem)).ToList();
if (badAttributes.Count > 0)
badMethods.Add($"{string.Join("\n", badAttributes.Select(x => (x as MenuItem).menuItem))}\n(Method '{method.Name}')\n");
}
}
if (badMethods.Count > 0)
affectedAssemblies.Add(kvp.Key, badMethods);
}
#endregion
if (affectedScripts.Count > 0 || affectedAssemblies.Count > 0)
{
if (affectedScripts.Count > 0)
{
result.Status = TestResultStatus.VariableSeverityIssue;
result.AddMessage("The following scripts contain invalid MenuItem names:");
foreach (var kvp in affectedScripts)
{
var message = string.Empty;
foreach (var type in kvp.Value)
message += type + "\n";
message = message.Remove(message.Length - "\n".Length);
result.AddMessage(message, null, kvp.Key);
}
}
if (affectedAssemblies.Count > 0)
{
result.Status = TestResultStatus.VariableSeverityIssue;
result.AddMessage("The following assemblies contain invalid MenuItem names:");
foreach (var kvp in affectedAssemblies)
{
var message = string.Empty;
foreach (var type in kvp.Value)
message += type + "\n";
message = message.Remove(message.Length - "\n".Length);
result.AddMessage(message, null, kvp.Key);
}
}
}
else
{
result.Status = TestResultStatus.Pass;
result.AddMessage("No MenuItems with invalid names were found!");
}
return result;
}
private bool IsValidMenuItem(string menuItemName)
{
var acceptableMenuItems = new string[]
{
"File",
"Edit",
"Assets",
"GameObject",
"Component",
"Window",
"Help",
"CONTEXT",
"Tools"
};
menuItemName = menuItemName.Replace("\\", "/");
if (acceptableMenuItems.Any(x => menuItemName.ToLower().StartsWith($"{x.ToLower()}/")))
return true;
return false;
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: d8e3b12ecc1fcd74d9a9f8d2b549fc63
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 115
packageName: Asset Store Publishing Tools
packageVersion: 12.0.1
assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckFileMenuNames.cs
uploadId: 724584

View File

@@ -0,0 +1,79 @@
using AssetStoreTools.Validator.Data;
using AssetStoreTools.Validator.Data.MessageActions;
using AssetStoreTools.Validator.Services.Validation;
using AssetStoreTools.Validator.TestDefinitions;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace AssetStoreTools.Validator.TestMethods
{
internal class CheckLODs : ITestScript
{
private GenericTestConfig _config;
private IAssetUtilityService _assetUtility;
public CheckLODs(GenericTestConfig config, IAssetUtilityService assetUtility)
{
_config = config;
_assetUtility = assetUtility;
}
public TestResult Run()
{
var result = new TestResult() { Status = TestResultStatus.Undefined };
var prefabs = _assetUtility.GetObjectsFromAssets<GameObject>(_config.ValidationPaths, AssetType.Prefab);
var badPrefabs = new Dictionary<GameObject, List<MeshFilter>>();
foreach (var p in prefabs)
{
var meshFilters = p.GetComponentsInChildren<MeshFilter>(true);
var badMeshFilters = new List<MeshFilter>();
var lodGroups = p.GetComponentsInChildren<LODGroup>(true);
foreach (var mf in meshFilters)
{
if (mf.name.Contains("LOD") && !IsPartOfLodGroup(mf, lodGroups))
badMeshFilters.Add(mf);
}
if (badMeshFilters.Count > 0)
badPrefabs.Add(p, badMeshFilters);
}
if (badPrefabs.Count == 0)
{
result.Status = TestResultStatus.Pass;
result.AddMessage("All found prefabs are meeting the LOD requirements!");
return result;
}
result.Status = TestResultStatus.VariableSeverityIssue;
result.AddMessage("The following prefabs do not meet the LOD requirements");
foreach (var p in badPrefabs)
{
var resultList = new List<Object>();
resultList.Add(p.Key);
resultList.AddRange(p.Value);
result.AddMessage($"{p.Key.name}.prefab", new OpenAssetAction(p.Key), resultList.ToArray());
}
return result;
}
private bool IsPartOfLodGroup(MeshFilter mf, LODGroup[] lodGroups)
{
foreach (var lodGroup in lodGroups)
{
// If MeshFilter is a child/deep child of a LodGroup AND is referenced in this LOD group - it is valid
if (mf.transform.IsChildOf(lodGroup.transform) &&
lodGroup.GetLODs().Any(lod => lod.renderers.Any(renderer => renderer != null && renderer.gameObject == mf.gameObject)))
return true;
}
return false;
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 43b2158602f87704fa7b91561cfc8678
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 115
packageName: Asset Store Publishing Tools
packageVersion: 12.0.1
assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckLODs.cs
uploadId: 724584

View File

@@ -0,0 +1,77 @@
using AssetStoreTools.Validator.Data;
using AssetStoreTools.Validator.Services.Validation;
using AssetStoreTools.Validator.TestDefinitions;
using System;
using System.Collections.Concurrent;
using System.Threading.Tasks;
using UnityEditor;
using UnityObject = UnityEngine.Object;
namespace AssetStoreTools.Validator.TestMethods
{
internal class CheckLineEndings : ITestScript
{
private GenericTestConfig _config;
private IAssetUtilityService _assetUtility;
public CheckLineEndings(GenericTestConfig config, IAssetUtilityService assetUtility)
{
_config = config;
_assetUtility = assetUtility;
}
public TestResult Run()
{
var result = new TestResult() { Status = TestResultStatus.Undefined };
var scripts = _assetUtility.GetObjectsFromAssets<MonoScript>(_config.ValidationPaths, AssetType.MonoScript);
var affectedScripts = new ConcurrentBag<UnityObject>();
var scriptContents = new ConcurrentDictionary<MonoScript, string>();
// A separate dictionary is needed because MonoScript contents cannot be accessed outside of the main thread
foreach (var s in scripts)
if (s != null)
scriptContents.TryAdd(s, s.text);
Parallel.ForEach(scriptContents, (s) =>
{
if (HasInconsistentLineEndings(s.Value))
affectedScripts.Add(s.Key);
});
if (affectedScripts.Count > 0)
{
result.Status = TestResultStatus.VariableSeverityIssue;
result.AddMessage("The following scripts have inconsistent line endings:", null, affectedScripts.ToArray());
}
else
{
result.Status = TestResultStatus.Pass;
result.AddMessage("No scripts with inconsistent line endings were found!");
}
return result;
}
private bool HasInconsistentLineEndings(string text)
{
int crlfEndings = 0;
int lfEndings = 0;
var split = text.Split(new[] { "\n" }, StringSplitOptions.None);
for (int i = 0; i < split.Length; i++)
{
var line = split[i];
if (line.EndsWith("\r"))
crlfEndings++;
else if (i != split.Length - 1)
lfEndings++;
}
if (crlfEndings > 0 && lfEndings > 0)
return true;
return false;
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 85885005d1c594f42826de3555e98365
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 115
packageName: Asset Store Publishing Tools
packageVersion: 12.0.1
assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckLineEndings.cs
uploadId: 724584

View File

@@ -0,0 +1,106 @@
using AssetStoreTools.Validator.Data;
using AssetStoreTools.Validator.Services.Validation;
using AssetStoreTools.Validator.TestDefinitions;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace AssetStoreTools.Validator.TestMethods
{
internal class CheckMeshPrefabs : ITestScript
{
private GenericTestConfig _config;
private IAssetUtilityService _assetUtility;
private IMeshUtilityService _meshUtility;
public CheckMeshPrefabs(GenericTestConfig config, IAssetUtilityService assetUtility, IMeshUtilityService meshUtility)
{
_config = config;
_assetUtility = assetUtility;
_meshUtility = meshUtility;
}
public TestResult Run()
{
var result = new TestResult() { Status = TestResultStatus.Undefined };
var usedModelPaths = new List<string>();
var prefabs = _assetUtility.GetObjectsFromAssets<GameObject>(_config.ValidationPaths, AssetType.Prefab);
var missingMeshReferencePrefabs = new List<GameObject>();
// Get all meshes in existing prefabs and check if prefab has missing mesh references
foreach (var p in prefabs)
{
var meshes = _meshUtility.GetCustomMeshesInObject(p);
foreach (var mesh in meshes)
{
string meshPath = _assetUtility.ObjectToAssetPath(mesh);
usedModelPaths.Add(meshPath);
}
if (HasMissingMeshReferences(p))
missingMeshReferencePrefabs.Add(p);
}
// Get all meshes in existing models
var allModelPaths = GetAllModelMeshPaths(_config.ValidationPaths);
// Get the list of meshes without prefabs
List<string> unusedModels = allModelPaths.Except(usedModelPaths).ToList();
if (unusedModels.Count == 0)
{
result.Status = TestResultStatus.Pass;
result.AddMessage("All found prefabs have meshes!");
return result;
}
result.Status = TestResultStatus.VariableSeverityIssue;
var models = unusedModels.Select(_assetUtility.AssetPathToObject).ToArray();
result.AddMessage("The following models do not have associated prefabs", null, models);
if (missingMeshReferencePrefabs.Count > 0)
result.AddMessage("The following prefabs have missing mesh references", null, missingMeshReferencePrefabs.ToArray());
return result;
}
private IEnumerable<string> GetAllModelMeshPaths(string[] validationPaths)
{
var models = _assetUtility.GetObjectsFromAssets(validationPaths, AssetType.Model);
var paths = new List<string>();
foreach (var o in models)
{
var m = (GameObject)o;
var modelPath = _assetUtility.ObjectToAssetPath(m);
var assetImporter = _assetUtility.GetAssetImporter(modelPath);
if (assetImporter is UnityEditor.ModelImporter modelImporter)
{
var clips = modelImporter.clipAnimations.Count();
var meshes = _meshUtility.GetCustomMeshesInObject(m);
// Only add if the model has meshes and no clips
if (meshes.Any() && clips == 0)
paths.Add(modelPath);
}
}
return paths;
}
private bool HasMissingMeshReferences(GameObject go)
{
var meshes = go.GetComponentsInChildren<MeshFilter>(true);
var skinnedMeshes = go.GetComponentsInChildren<SkinnedMeshRenderer>(true);
if (meshes.Length == 0 && skinnedMeshes.Length == 0)
return false;
if (meshes.Any(x => x.sharedMesh == null) || skinnedMeshes.Any(x => x.sharedMesh == null))
return true;
return false;
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 3c3d0d642ac6a6a48aa124a93dae3734
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 115
packageName: Asset Store Publishing Tools
packageVersion: 12.0.1
assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckMeshPrefabs.cs
uploadId: 724584

View File

@@ -0,0 +1,66 @@
using AssetStoreTools.Validator.Data;
using AssetStoreTools.Validator.Services.Validation;
using AssetStoreTools.Validator.TestDefinitions;
using System.Collections.Generic;
using UnityEngine;
namespace AssetStoreTools.Validator.TestMethods
{
internal class CheckMissingComponentsinAssets : ITestScript
{
private GenericTestConfig _config;
private IAssetUtilityService _assetUtility;
public CheckMissingComponentsinAssets(GenericTestConfig config, IAssetUtilityService assetUtility)
{
_config = config;
_assetUtility = assetUtility;
}
public TestResult Run()
{
var result = new TestResult() { Status = TestResultStatus.Undefined };
var assets = GetAllAssetsWithMissingComponents(_config.ValidationPaths);
if (assets.Length == 0)
{
result.Status = TestResultStatus.Pass;
result.AddMessage("No assets have missing components!");
return result;
}
result.Status = TestResultStatus.VariableSeverityIssue;
result.AddMessage("The following assets contain missing components", null, assets);
return result;
}
private GameObject[] GetAllAssetsWithMissingComponents(string[] validationPaths)
{
var missingReferenceAssets = new List<GameObject>();
var prefabObjects = _assetUtility.GetObjectsFromAssets<GameObject>(validationPaths, AssetType.Prefab);
foreach (var p in prefabObjects)
{
if (p != null && IsMissingReference(p))
missingReferenceAssets.Add(p);
}
return missingReferenceAssets.ToArray();
}
private bool IsMissingReference(GameObject asset)
{
var components = asset.GetComponentsInChildren<Component>();
foreach (var c in components)
{
if (!c)
return true;
}
return false;
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 22d8f814e2363e34ea220736a4042728
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 115
packageName: Asset Store Publishing Tools
packageVersion: 12.0.1
assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckMissingComponentsinAssets.cs
uploadId: 724584

View File

@@ -0,0 +1,93 @@
using AssetStoreTools.Validator.Data;
using AssetStoreTools.Validator.Data.MessageActions;
using AssetStoreTools.Validator.Services.Validation;
using AssetStoreTools.Validator.TestDefinitions;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using SceneAsset = UnityEditor.SceneAsset;
namespace AssetStoreTools.Validator.TestMethods
{
internal class CheckMissingComponentsinScenes : ITestScript
{
private GenericTestConfig _config;
private IAssetUtilityService _assetUtility;
private ISceneUtilityService _sceneUtility;
public CheckMissingComponentsinScenes(GenericTestConfig config, IAssetUtilityService assetUtility, ISceneUtilityService sceneUtility)
{
_config = config;
_assetUtility = assetUtility;
_sceneUtility = sceneUtility;
}
public TestResult Run()
{
var result = new TestResult() { Status = TestResultStatus.Undefined };
var originalScenePath = _sceneUtility.CurrentScenePath;
var scenePaths = _assetUtility.GetAssetPathsFromAssets(_config.ValidationPaths, AssetType.Scene);
foreach (var scenePath in scenePaths)
{
var missingComponentGOs = GetMissingComponentGOsInScene(scenePath);
if (missingComponentGOs.Count == 0)
continue;
result.Status = TestResultStatus.VariableSeverityIssue;
var message = $"GameObjects with missing components or prefab references found in {scenePath}.\n\nClick this message to open the Scene and see the affected GameObjects:";
result.AddMessage(message, new OpenAssetAction(_assetUtility.AssetPathToObject<SceneAsset>(scenePath)), missingComponentGOs.ToArray());
}
_sceneUtility.OpenScene(originalScenePath);
if (result.Status == TestResultStatus.Undefined)
{
result.Status = TestResultStatus.Pass;
result.AddMessage("No missing components were found!");
}
return result;
}
private List<GameObject> GetMissingComponentGOsInScene(string path)
{
var missingComponentGOs = new List<GameObject>();
var scene = _sceneUtility.OpenScene(path);
if (!scene.IsValid())
{
Debug.LogWarning("Unable to get Scene in " + path);
return new List<GameObject>();
}
var rootObjects = scene.GetRootGameObjects();
foreach (var obj in rootObjects)
{
missingComponentGOs.AddRange(GetMissingComponentGOs(obj));
}
return missingComponentGOs;
}
private List<GameObject> GetMissingComponentGOs(GameObject root)
{
var missingComponentGOs = new List<GameObject>();
var rootComponents = root.GetComponents<Component>();
if (UnityEditor.PrefabUtility.GetPrefabInstanceStatus(root) == UnityEditor.PrefabInstanceStatus.MissingAsset || rootComponents.Any(c => !c))
{
missingComponentGOs.Add(root);
}
foreach (Transform child in root.transform)
missingComponentGOs.AddRange(GetMissingComponentGOs(child.gameObject));
return missingComponentGOs;
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 511e76d0ebcb23d40a7b49dda0e2980f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 115
packageName: Asset Store Publishing Tools
packageVersion: 12.0.1
assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckMissingComponentsinScenes.cs
uploadId: 724584

View File

@@ -0,0 +1,64 @@
using AssetStoreTools.Validator.Data;
using AssetStoreTools.Validator.Services.Validation;
using AssetStoreTools.Validator.TestDefinitions;
using System.Collections.Generic;
using System.Linq;
using UnityObject = UnityEngine.Object;
namespace AssetStoreTools.Validator.TestMethods
{
internal class CheckModelImportLogs : ITestScript
{
private GenericTestConfig _config;
private IAssetUtilityService _assetUtility;
private IModelUtilityService _modelUtility;
public CheckModelImportLogs(GenericTestConfig config, IAssetUtilityService assetUtility, IModelUtilityService modelUtility)
{
_config = config;
_assetUtility = assetUtility;
_modelUtility = modelUtility;
}
public TestResult Run()
{
var result = new TestResult() { Status = TestResultStatus.Undefined };
var models = _assetUtility.GetObjectsFromAssets<UnityObject>(_config.ValidationPaths, AssetType.Model);
var importLogs = _modelUtility.GetImportLogs(models.ToArray());
var warningModels = new List<UnityObject>();
var errorModels = new List<UnityObject>();
foreach (var kvp in importLogs)
{
if (kvp.Value.Any(x => x.Severity == UnityEngine.LogType.Error))
errorModels.Add(kvp.Key);
if (kvp.Value.Any(x => x.Severity == UnityEngine.LogType.Warning))
warningModels.Add(kvp.Key);
}
if (warningModels.Count > 0 || errorModels.Count > 0)
{
if (warningModels.Count > 0)
{
result.Status = TestResultStatus.Warning;
result.AddMessage("The following models contain import warnings:", null, warningModels.ToArray());
}
if (errorModels.Count > 0)
{
result.Status = TestResultStatus.Warning;
result.AddMessage("The following models contain import errors:", null, errorModels.ToArray());
}
}
else
{
result.Status = TestResultStatus.Pass;
result.AddMessage("No issues were detected when importing your models!");
}
return result;
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 98f3ec209166855408eaf4abe5bff591
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 115
packageName: Asset Store Publishing Tools
packageVersion: 12.0.1
assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckModelImportLogs.cs
uploadId: 724584

View File

@@ -0,0 +1,71 @@
using AssetStoreTools.Validator.Data;
using AssetStoreTools.Validator.Services.Validation;
using AssetStoreTools.Validator.TestDefinitions;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace AssetStoreTools.Validator.TestMethods
{
internal class CheckModelOrientation : ITestScript
{
private GenericTestConfig _config;
private IAssetUtilityService _assetUtility;
private IMeshUtilityService _meshUtility;
public CheckModelOrientation(GenericTestConfig config, IAssetUtilityService assetUtility, IMeshUtilityService meshUtility)
{
_config = config;
_assetUtility = assetUtility;
_meshUtility = meshUtility;
}
public TestResult Run()
{
var result = new TestResult() { Status = TestResultStatus.Undefined };
var models = _assetUtility.GetObjectsFromAssets<GameObject>(_config.ValidationPaths, AssetType.Model);
var badModels = new List<GameObject>();
foreach (var m in models)
{
var meshes = _meshUtility.GetCustomMeshesInObject(m);
var assetImporter = _assetUtility.GetAssetImporter(m);
if (!(assetImporter is UnityEditor.ModelImporter modelImporter))
continue;
var clips = modelImporter.clipAnimations.Length;
// Only check if the model has meshes and no clips
if (!meshes.Any() || clips != 0)
continue;
Transform[] transforms = m.GetComponentsInChildren<Transform>(true);
foreach (var t in transforms)
{
var hasMeshComponent = t.TryGetComponent<MeshFilter>(out _) || t.TryGetComponent<SkinnedMeshRenderer>(out _);
if (t.localRotation == Quaternion.identity || !hasMeshComponent)
continue;
badModels.Add(m);
break;
}
}
if (badModels.Count == 0)
{
result.Status = TestResultStatus.Pass;
result.AddMessage("All found models are facing the right way!");
return result;
}
result.Status = TestResultStatus.VariableSeverityIssue;
result.AddMessage("The following models have incorrect rotation", null, badModels.ToArray());
return result;
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 56cdcdc41a80fbc46b5b2b83ec8d66d7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 115
packageName: Asset Store Publishing Tools
packageVersion: 12.0.1
assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckModelOrientation.cs
uploadId: 724584

View File

@@ -0,0 +1,58 @@
using AssetStoreTools.Validator.Data;
using AssetStoreTools.Validator.Services.Validation;
using AssetStoreTools.Validator.TestDefinitions;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityObject = UnityEngine.Object;
namespace AssetStoreTools.Validator.TestMethods
{
internal class CheckModelTypes : ITestScript
{
private GenericTestConfig _config;
private IAssetUtilityService _assetUtility;
public CheckModelTypes(GenericTestConfig config, IAssetUtilityService assetUtility)
{
_config = config;
_assetUtility = assetUtility;
}
public TestResult Run()
{
var result = new TestResult() { Status = TestResultStatus.Undefined };
var allowedExtensions = new string[] { ".fbx", ".dae", ".abc", ".obj" };
// Should retrieve All assets and not models here since ADB will not recognize certain
// types if appropriate software is not installed (e.g. .blend without Blender)
var allAssetPaths = _assetUtility.GetAssetPathsFromAssets(_config.ValidationPaths, AssetType.All);
var badModels = new List<UnityObject>();
foreach (var assetPath in allAssetPaths)
{
var importer = _assetUtility.GetAssetImporter(assetPath);
if (importer == null || !(importer is ModelImporter))
continue;
if (allowedExtensions.Any(x => importer.assetPath.ToLower().EndsWith(x)))
continue;
badModels.Add(_assetUtility.AssetPathToObject(assetPath));
}
if (badModels.Count == 0)
{
result.Status = TestResultStatus.Pass;
result.AddMessage("All models are of allowed formats!");
}
else
{
result.Status = TestResultStatus.VariableSeverityIssue;
result.AddMessage("The following models are of formats that should not be used for Asset Store packages:", null, badModels.ToArray());
}
return result;
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 428b1fb838e6f5a469bbfd26ca3fbfd2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 115
packageName: Asset Store Publishing Tools
packageVersion: 12.0.1
assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckModelTypes.cs
uploadId: 724584

View File

@@ -0,0 +1,94 @@
using AssetStoreTools.Validator.Data;
using AssetStoreTools.Validator.Services.Validation;
using AssetStoreTools.Validator.TestDefinitions;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
namespace AssetStoreTools.Validator.TestMethods
{
internal class CheckNormalMapTextures : ITestScript
{
public const int TextureCacheLimit = 8;
private GenericTestConfig _config;
private IAssetUtilityService _assetUtility;
public CheckNormalMapTextures(GenericTestConfig config, IAssetUtilityService assetUtility)
{
_config = config;
_assetUtility = assetUtility;
}
public TestResult Run()
{
var result = new TestResult() { Status = TestResultStatus.Undefined };
var materials = _assetUtility.GetObjectsFromAssets<Material>(_config.ValidationPaths, AssetType.Material);
var badTextures = new List<Texture>();
var badPaths = new List<string>();
foreach (var mat in materials)
{
for (int i = 0; i < mat.shader.GetPropertyCount(); i++)
{
if ((mat.shader.GetPropertyFlags(i) & UnityEngine.Rendering.ShaderPropertyFlags.Normal) != 0)
{
var propertyName = mat.shader.GetPropertyName(i);
var assignedTexture = mat.GetTexture(propertyName);
if (assignedTexture == null)
continue;
var texturePath = _assetUtility.ObjectToAssetPath(assignedTexture);
var textureImporter = _assetUtility.GetAssetImporter(texturePath) as TextureImporter;
if (textureImporter == null)
continue;
if (textureImporter.textureType != TextureImporterType.NormalMap && !badTextures.Contains(assignedTexture))
{
if (badTextures.Count < TextureCacheLimit)
{
badTextures.Add(assignedTexture);
}
else
{
string path = AssetDatabase.GetAssetPath(assignedTexture);
badPaths.Add(path);
}
}
}
}
EditorUtility.UnloadUnusedAssetsImmediate();
}
if (badTextures.Count == 0)
{
result.Status = TestResultStatus.Pass;
result.AddMessage("All normal map textures have the correct texture type!");
}
else if (badPaths.Count != 0)
{
foreach (Texture texture in badTextures)
{
string path = AssetDatabase.GetAssetPath(texture);
badPaths.Add(path);
}
string paths = string.Join("\n", badPaths);
result.Status = TestResultStatus.VariableSeverityIssue;
result.AddMessage("The following textures are not set to type 'Normal Map'", null);
result.AddMessage(paths);
}
else
{
result.Status = TestResultStatus.VariableSeverityIssue;
result.AddMessage("The following textures are not set to type 'Normal Map'", null, badTextures.ToArray());
}
return result;
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: d55cea510248f814eb2194c2b53f88d2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 115
packageName: Asset Store Publishing Tools
packageVersion: 12.0.1
assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckNormalMapTextures.cs
uploadId: 724584

View File

@@ -0,0 +1,295 @@
using AssetStoreTools.Utility;
using AssetStoreTools.Validator.Data;
using AssetStoreTools.Validator.Services.Validation;
using AssetStoreTools.Validator.TestDefinitions;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEngine;
namespace AssetStoreTools.Validator.TestMethods
{
internal class CheckPackageNaming : ITestScript
{
private const string ForbiddenCharacters = "~`!@#$%^&*()-_=+[{]}\\|;:'\",<>?/";
private readonly string[] PathsToCheckForForbiddenCharacters = new string[]
{
"Assets/",
"Assets/Editor/",
"Assets/Plugins/",
"Assets/Resources/",
"Assets/StreamingAssets/",
"Assets/WebGLTemplates/"
};
private class PathCheckResult
{
public Object[] InvalidMainPaths;
public Object[] InvalidMainPathContentPaths;
public Object[] InvalidMainPathLeadingUpPaths;
public Object[] InvalidHybridPackages;
public Object[] PotentiallyInvalidContent;
public bool HasIssues => InvalidMainPaths.Length > 0
|| InvalidMainPathContentPaths.Length > 0
|| InvalidMainPathLeadingUpPaths.Length > 0
|| InvalidHybridPackages.Length > 0
|| PotentiallyInvalidContent.Length > 0;
}
private GenericTestConfig _config;
private IAssetUtilityService _assetUtility;
// Constructor also accepts dependency injection of registered IValidatorService types
public CheckPackageNaming(GenericTestConfig config, IAssetUtilityService assetUtility)
{
_config = config;
_assetUtility = assetUtility;
}
public TestResult Run()
{
var result = new TestResult() { Status = TestResultStatus.Undefined };
var checkResult = GetInvalidPathsInAssets();
if (checkResult.HasIssues)
{
result.Status = TestResultStatus.Warning;
if (checkResult.InvalidMainPaths.Length > 0)
{
result.Status = TestResultStatus.VariableSeverityIssue;
result.AddMessage("The following assets appear to be artificially bumped up in the project hierarchy within commonly used folders", null, checkResult.InvalidMainPaths);
}
if (checkResult.InvalidMainPathContentPaths.Length > 0)
{
result.Status = TestResultStatus.VariableSeverityIssue;
result.AddMessage("The following assets appear to be artificially bumped up in the project hierarchy within commonly used folders", null, checkResult.InvalidMainPathContentPaths);
}
if (checkResult.InvalidMainPathLeadingUpPaths.Length > 0)
{
result.Status = TestResultStatus.VariableSeverityIssue;
result.AddMessage("Despite not being directly validated, this path would be automatically created by the Unity Importer when importing your package", null, checkResult.InvalidMainPathLeadingUpPaths);
}
if (checkResult.InvalidHybridPackages.Length > 0)
{
result.Status = TestResultStatus.VariableSeverityIssue;
result.AddMessage("The following packages appear to be artificially bumped up in the Package hierarchy with their 'Display Name' configuration", null, checkResult.InvalidHybridPackages);
}
if (checkResult.PotentiallyInvalidContent.Length > 0)
{
// Do not override previously set severities
result.AddMessage("It is recommended that nested package content refrains from starting with a special character", null, checkResult.PotentiallyInvalidContent);
}
}
else
{
result.Status = TestResultStatus.Pass;
result.AddMessage("All package asset names are valid!");
}
return result;
}
private PathCheckResult GetInvalidPathsInAssets()
{
var allInvalidMainPaths = new List<string>();
var allInvalidMainContentPaths = new List<string>();
var allInvalidMainLeadingUpPaths = new List<string>();
var allInvalidPackagePaths = new List<string>();
var allInvalidOtherContentPaths = new List<string>();
foreach (var validationPath in _config.ValidationPaths)
{
// Is path itself not forbidden e.g.: when validating Assets/_Package, the folder _Package would be invalid
if (!IsDirectMainPathValid(validationPath))
allInvalidMainPaths.Add(validationPath);
// Are path contents not forbidden e.g.: when validating Assets/, the folder _Package would be invalid
if (!IsDirectMainPathContentValid(validationPath, out var invalidContentPaths))
allInvalidMainContentPaths.AddRange(invalidContentPaths);
// Is the path leading up to this path not forbidden e.g: when validating Assets/_WorkDir/Package, the folder _Workdir would be invalid
if (!IsPathLeadingUpToMainPathValid(validationPath, out var invalidLeadingUpPath))
allInvalidMainLeadingUpPaths.Add(invalidLeadingUpPath);
// Is the path pointing to a package valid, e.g.: when validating Packages/com.company.product its display name _Product would be invalid
if (!IsHybridPackageMainPathValid(validationPath, out string invalidPackagePath))
allInvalidPackagePaths.Add(invalidPackagePath);
}
var ignoredPaths = new List<string>();
ignoredPaths.AddRange(allInvalidMainPaths);
ignoredPaths.AddRange(allInvalidMainContentPaths);
ignoredPaths.AddRange(allInvalidMainLeadingUpPaths);
ignoredPaths.AddRange(allInvalidPackagePaths);
// Mark any other paths that start with a forbidden character
if (!ArePackageContentsValid(ignoredPaths, out var invalidContents))
allInvalidOtherContentPaths.AddRange(invalidContents);
return new PathCheckResult()
{
InvalidMainPaths = PathsToObjects(allInvalidMainPaths),
InvalidMainPathContentPaths = PathsToObjects(allInvalidMainContentPaths),
InvalidMainPathLeadingUpPaths = PathsToObjects(allInvalidMainLeadingUpPaths),
InvalidHybridPackages = PathsToObjects(allInvalidPackagePaths),
PotentiallyInvalidContent = PathsToObjects(allInvalidOtherContentPaths)
};
}
private bool IsDirectMainPathValid(string validationPath)
{
foreach (var forbiddenPath in PathsToCheckForForbiddenCharacters)
{
var forbiddenPathWithSeparator = forbiddenPath.EndsWith("/") ? forbiddenPath : forbiddenPath + "/";
if (!validationPath.StartsWith(forbiddenPathWithSeparator))
continue;
var truncatedPath = validationPath.Remove(0, forbiddenPathWithSeparator.Length);
var truncatedPathSplit = truncatedPath.Split('/');
// It is not a direct main path if it has deeper paths
if (truncatedPathSplit.Length != 1)
continue;
if (ForbiddenCharacters.Any(x => truncatedPath.StartsWith(x.ToString())))
return false;
}
return true;
}
private bool IsDirectMainPathContentValid(string validationPath, out List<string> invalidContentPaths)
{
invalidContentPaths = new List<string>();
var contents = Directory.EnumerateFileSystemEntries(validationPath, "*", SearchOption.AllDirectories)
.Where(x => !x.EndsWith(".meta"))
.Select(GetAdbPath);
foreach (var contentPath in contents)
{
foreach (var forbiddenPath in PathsToCheckForForbiddenCharacters)
{
var forbiddenPathWithSeparator = forbiddenPath.EndsWith("/") ? forbiddenPath : forbiddenPath + "/";
if (!contentPath.StartsWith(forbiddenPathWithSeparator))
continue;
var truncatedPath = contentPath.Remove(0, forbiddenPathWithSeparator.Length);
var truncatedPathSplit = truncatedPath.Split('/');
// Only check the first level of content relative to the forbidden path
if (truncatedPathSplit.Length > 1)
continue;
if (ForbiddenCharacters.Any(x => truncatedPathSplit[0].StartsWith(x.ToString())))
invalidContentPaths.Add(contentPath);
}
}
return invalidContentPaths.Count == 0;
}
private bool IsPathLeadingUpToMainPathValid(string validationPath, out string invalidLeadingUpPath)
{
invalidLeadingUpPath = string.Empty;
foreach (var forbiddenPath in PathsToCheckForForbiddenCharacters)
{
var forbiddenPathWithSeparator = forbiddenPath.EndsWith("/") ? forbiddenPath : forbiddenPath + "/";
if (!validationPath.StartsWith(forbiddenPathWithSeparator))
continue;
var truncatedPath = validationPath.Remove(0, forbiddenPathWithSeparator.Length);
var truncatedPathSplit = truncatedPath.Split('/');
// It is not a leading up path if it has no deeper path
if (truncatedPathSplit.Length == 1)
continue;
if (ForbiddenCharacters.Any(x => truncatedPathSplit[0].StartsWith(x.ToString())))
{
invalidLeadingUpPath = forbiddenPathWithSeparator + truncatedPathSplit[0];
return false;
}
}
return true;
}
private bool IsHybridPackageMainPathValid(string validationPath, out string invalidPackagePath)
{
invalidPackagePath = string.Empty;
if (!PackageUtility.GetPackageByManifestPath($"{validationPath}/package.json", out var package))
return true;
var packageName = package.displayName;
if (ForbiddenCharacters.Any(x => packageName.StartsWith(x.ToString())))
{
invalidPackagePath = validationPath;
return false;
}
return true;
}
private bool ArePackageContentsValid(IEnumerable<string> ignoredPaths, out List<string> invalidContentPaths)
{
invalidContentPaths = new List<string>();
foreach (var validationPath in _config.ValidationPaths)
{
var validationPathFolderName = validationPath.Split('/').Last();
if (!ignoredPaths.Contains(validationPath) && ForbiddenCharacters.Any(x => validationPathFolderName.StartsWith(x.ToString())))
invalidContentPaths.Add(validationPath);
var contents = Directory.EnumerateFileSystemEntries(validationPath, "*", SearchOption.AllDirectories)
.Where(x => !x.EndsWith(".meta"))
.Select(GetAdbPath);
foreach (var contentEntry in contents)
{
if (ignoredPaths.Contains(contentEntry))
continue;
var entryName = contentEntry.Split('/').Last();
if (ForbiddenCharacters.Any(x => entryName.StartsWith(x.ToString())))
invalidContentPaths.Add(contentEntry);
}
}
return invalidContentPaths.Count == 0;
}
private string GetAdbPath(string path)
{
path = path.Replace("\\", "/");
if (path.StartsWith(Constants.RootProjectPath))
path = path.Remove(Constants.RootProjectPath.Length);
return path;
}
private Object[] PathsToObjects(IEnumerable<string> paths)
{
var objects = new List<Object>();
foreach (var path in paths)
{
var obj = _assetUtility.AssetPathToObject(path);
if (obj != null)
objects.Add(obj);
}
return objects.ToArray();
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: afe9e04825c7d904981a54404b222290
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 115
packageName: Asset Store Publishing Tools
packageVersion: 12.0.1
assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckPackageNaming.cs
uploadId: 724584

View File

@@ -0,0 +1,76 @@
using AssetStoreTools.Validator.Data;
using AssetStoreTools.Validator.Data.MessageActions;
using AssetStoreTools.Validator.Services.Validation;
using AssetStoreTools.Validator.TestDefinitions;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
namespace AssetStoreTools.Validator.TestMethods
{
internal class CheckParticleSystems : ITestScript
{
private GenericTestConfig _config;
private IAssetUtilityService _assetUtility;
private ISceneUtilityService _sceneUtility;
public CheckParticleSystems(GenericTestConfig config, IAssetUtilityService assetUtility, ISceneUtilityService sceneUtility)
{
_config = config;
_assetUtility = assetUtility;
_sceneUtility = sceneUtility;
}
public TestResult Run()
{
var result = new TestResult() { Status = TestResultStatus.Undefined };
var originalScenePath = _sceneUtility.CurrentScenePath;
var scenePaths = _assetUtility.GetAssetPathsFromAssets(_config.ValidationPaths, AssetType.Scene);
foreach (var path in scenePaths)
{
var badParticleSystems = new List<ParticleSystem>();
var scene = _sceneUtility.OpenScene(path);
if (!scene.IsValid())
{
Debug.LogWarning("Unable to get Scene in " + path);
continue;
}
#if UNITY_2023_1_OR_NEWER
var particleSystems = GameObject.FindObjectsByType<ParticleSystem>(FindObjectsInactive.Include, FindObjectsSortMode.None);
#else
var particleSystems = GameObject.FindObjectsOfType<ParticleSystem>();
#endif
foreach (var ps in particleSystems)
{
if (PrefabUtility.IsPartOfAnyPrefab(ps.gameObject))
continue;
badParticleSystems.Add(ps);
}
if (badParticleSystems.Count == 0)
continue;
result.Status = TestResultStatus.VariableSeverityIssue;
var message = $"Particle Systems not belonging to any Prefab were found in {path}.\n\nClick this message to open the Scene and see the affected Particle Systems:";
result.AddMessage(message, new OpenAssetAction(AssetDatabase.LoadAssetAtPath<SceneAsset>(path)), badParticleSystems.ToArray());
}
_sceneUtility.OpenScene(originalScenePath);
if (result.Status == TestResultStatus.Undefined)
{
result.Status = TestResultStatus.Pass;
result.AddMessage("No Particle Systems without Prefabs were found!");
}
return result;
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 6a623f7988c75884bb17b169ccd3e993
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 115
packageName: Asset Store Publishing Tools
packageVersion: 12.0.1
assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckParticleSystems.cs
uploadId: 724584

View File

@@ -0,0 +1,98 @@
using AssetStoreTools.Validator.Data;
using AssetStoreTools.Validator.Services.Validation;
using AssetStoreTools.Validator.TestDefinitions;
using AssetStoreTools.Validator.Utility;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityObject = UnityEngine.Object;
namespace AssetStoreTools.Validator.TestMethods
{
internal class CheckPathLengths : ITestScript
{
private GenericTestConfig _config;
private IAssetUtilityService _assetUtility;
public CheckPathLengths(GenericTestConfig config, IAssetUtilityService assetUtility)
{
_config = config;
_assetUtility = assetUtility;
}
public TestResult Run()
{
TestResult result = new TestResult();
int pathLengthLimit = 140;
// Get all project paths and sort by length so that folders always come before files
var allPaths = ValidatorUtility.GetProjectPaths(_config.ValidationPaths).OrderBy(x => x.Length);
var filteredDirs = new Dictionary<string, UnityObject>();
var filteredFiles = new Dictionary<string, UnityObject>();
foreach (var path in allPaths)
{
// Truncated path examples:
// Assets/[Scenes/SampleScene.unity]
// Packages/com.example.package/[Editor/EditorScript.cs]
var truncatedPath = path;
if (path.StartsWith("Assets/"))
truncatedPath = path.Remove(0, "Assets/".Length);
else if (path.StartsWith("Packages/"))
{
var splitPath = path.Split('/');
truncatedPath = string.Join("/", splitPath.Skip(2));
}
// Skip paths under the character limit
if (truncatedPath.Length < pathLengthLimit)
continue;
// Skip children of already added directories
if (filteredDirs.Keys.Any(x => truncatedPath.StartsWith(x)))
continue;
if (AssetDatabase.IsValidFolder(path))
{
filteredDirs.Add(truncatedPath, _assetUtility.AssetPathToObject(path));
continue;
}
if (!filteredFiles.ContainsKey(truncatedPath))
filteredFiles.Add(truncatedPath, _assetUtility.AssetPathToObject(path));
}
if (filteredDirs.Count == 0 && filteredFiles.Count == 0)
{
result.Status = TestResultStatus.Pass;
result.AddMessage("All package content matches the path limit criteria!");
return result;
}
if (filteredDirs.Count > 0)
{
var maxDirLength = filteredDirs.Keys.Aggregate("", (max, cur) => max.Length > cur.Length ? max : cur);
result.Status = TestResultStatus.VariableSeverityIssue;
result.AddMessage($"The following folders exceed the path length limit:");
foreach (var kvp in filteredDirs)
{
result.AddMessage($"Path length: {kvp.Key.Length} characters", null, kvp.Value);
}
}
if (filteredFiles.Count > 0)
{
var maxFileLength = filteredFiles.Keys.Aggregate("", (max, cur) => max.Length > cur.Length ? max : cur);
result.Status = TestResultStatus.VariableSeverityIssue;
result.AddMessage($"The following files exceed the path length limit:");
foreach (var kvp in filteredFiles)
{
result.AddMessage($"Path length: {kvp.Key.Length} characters", null, kvp.Value);
}
}
return result;
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: ae379305e9165e84584373a8272c09e7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 115
packageName: Asset Store Publishing Tools
packageVersion: 12.0.1
assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckPathLengths.cs
uploadId: 724584

View File

@@ -0,0 +1,71 @@
using AssetStoreTools.Validator.Data;
using AssetStoreTools.Validator.Services.Validation;
using AssetStoreTools.Validator.TestDefinitions;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace AssetStoreTools.Validator.TestMethods
{
internal class CheckPrefabTransforms : ITestScript
{
private GenericTestConfig _config;
private IAssetUtilityService _assetUtility;
private IMeshUtilityService _meshUtility;
public CheckPrefabTransforms(GenericTestConfig config, IAssetUtilityService assetUtility, IMeshUtilityService meshUtility)
{
_config = config;
_assetUtility = assetUtility;
_meshUtility = meshUtility;
}
public TestResult Run()
{
var result = new TestResult() { Status = TestResultStatus.Undefined };
var prefabs = _assetUtility.GetObjectsFromAssets<GameObject>(_config.ValidationPaths, AssetType.Prefab);
var badPrefabs = new List<GameObject>();
var badPrefabsLowOffset = new List<GameObject>();
foreach (var p in prefabs)
{
var hasRectTransform = p.TryGetComponent(out RectTransform _);
if (hasRectTransform || !_meshUtility.GetCustomMeshesInObject(p).Any())
continue;
var positionString = p.transform.position.ToString("F12");
var rotationString = p.transform.rotation.eulerAngles.ToString("F12");
var localScaleString = p.transform.localScale.ToString("F12");
var vectorZeroString = Vector3.zero.ToString("F12");
var vectorOneString = Vector3.one.ToString("F12");
if (positionString != vectorZeroString || rotationString != vectorZeroString || localScaleString != vectorOneString)
{
if (p.transform.position == Vector3.zero && p.transform.rotation.eulerAngles == Vector3.zero && p.transform.localScale == Vector3.one)
badPrefabsLowOffset.Add(p);
else
badPrefabs.Add(p);
}
}
if (badPrefabs.Count == 0 && badPrefabsLowOffset.Count == 0)
{
result.Status = TestResultStatus.Pass;
result.AddMessage("All found prefabs were reset!");
return result;
}
result.Status = TestResultStatus.VariableSeverityIssue;
if (badPrefabs.Count > 0)
result.AddMessage("The following prefabs' transforms do not fit the requirements", null, badPrefabs.ToArray());
if (badPrefabsLowOffset.Count > 0)
result.AddMessage("The following prefabs have unusually low transform values, which might not be accurately displayed " +
"in the Inspector window. Please use the 'Debug' Inspector mode to review the Transform component of these prefabs " +
"or reset the Transform components using the right-click context menu", null, badPrefabsLowOffset.ToArray());
return result;
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: f712c17a60bf2d049a4e61c8f79e56c2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 115
packageName: Asset Store Publishing Tools
packageVersion: 12.0.1
assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckPrefabTransforms.cs
uploadId: 724584

View File

@@ -0,0 +1,30 @@
using AssetStoreTools.Validator.Data;
using AssetStoreTools.Validator.TestDefinitions;
using UnityEditor;
namespace AssetStoreTools.Validator.TestMethods
{
internal class CheckScriptCompilation : ITestScript
{
public TestResult Run()
{
var result = new TestResult() { Status = TestResultStatus.Undefined };
var hasCompilationErrors = EditorUtility.scriptCompilationFailed;
if (hasCompilationErrors)
{
result.Status = TestResultStatus.VariableSeverityIssue;
result.AddMessage("One or more scripts in the project failed to compile.\n" +
"Please check the Console window to see the list of errors");
}
else
{
result.Status = TestResultStatus.Pass;
result.AddMessage("All scripts in the project compiled successfully!");
}
return result;
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 59db88f43969db8499299bce7f4fb967
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 115
packageName: Asset Store Publishing Tools
packageVersion: 12.0.1
assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckScriptCompilation.cs
uploadId: 724584

View File

@@ -0,0 +1,63 @@
using AssetStoreTools.Validator.Data;
using AssetStoreTools.Validator.Services.Validation;
using AssetStoreTools.Validator.TestDefinitions;
using System.Linq;
using UnityEditor;
using UnityEngine;
#if !UNITY_2023_1_OR_NEWER
using UnityEngine.Experimental.Rendering;
#endif
#if UNITY_2023_1_OR_NEWER
using UnityEngine.Rendering;
#endif
namespace AssetStoreTools.Validator.TestMethods
{
internal class CheckShaderCompilation : ITestScript
{
private GenericTestConfig _config;
private IAssetUtilityService _assetUtility;
public CheckShaderCompilation(GenericTestConfig config, IAssetUtilityService assetUtility)
{
_config = config;
_assetUtility = assetUtility;
}
public TestResult Run()
{
var result = new TestResult() { Status = TestResultStatus.Undefined };
var shaders = _assetUtility.GetObjectsFromAssets(_config.ValidationPaths, AssetType.Shader);
var badShaders = shaders.Where(ShaderHasError).ToArray();
if (badShaders.Length > 0)
{
result.Status = TestResultStatus.VariableSeverityIssue;
result.AddMessage("The following shader files have errors", null, badShaders);
}
else
{
result.Status = TestResultStatus.Pass;
result.AddMessage("All found Shaders have no compilation errors!");
}
return result;
}
private bool ShaderHasError(Object obj)
{
switch (obj)
{
case Shader shader:
return ShaderUtil.ShaderHasError(shader);
case ComputeShader shader:
return ShaderUtil.GetComputeShaderMessageCount(shader) > 0;
case RayTracingShader shader:
return ShaderUtil.GetRayTracingShaderMessageCount(shader) > 0;
default:
return false;
}
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 7abb278a6082bde4391e0779394cb85b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 115
packageName: Asset Store Publishing Tools
packageVersion: 12.0.1
assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckShaderCompilation.cs
uploadId: 724584

View File

@@ -0,0 +1,57 @@
using AssetStoreTools.Validator.Data;
using AssetStoreTools.Validator.Services.Validation;
using AssetStoreTools.Validator.TestDefinitions;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
namespace AssetStoreTools.Validator.TestMethods
{
internal class CheckTextureDimensions : ITestScript
{
private GenericTestConfig _config;
private IAssetUtilityService _assetUtility;
public CheckTextureDimensions(GenericTestConfig config, IAssetUtilityService assetUtility)
{
_config = config;
_assetUtility = assetUtility;
}
public TestResult Run()
{
var result = new TestResult() { Status = TestResultStatus.Undefined };
var textures = _assetUtility.GetObjectsFromAssets<Texture>(_config.ValidationPaths, AssetType.Texture);
var badTextures = new List<Texture>();
foreach (var texture in textures)
{
if (Mathf.IsPowerOfTwo(texture.width) && Mathf.IsPowerOfTwo(texture.height))
continue;
var importer = _assetUtility.GetAssetImporter(_assetUtility.ObjectToAssetPath(texture));
if (importer == null || !(importer is TextureImporter textureImporter)
|| textureImporter.textureType == TextureImporterType.Sprite
|| textureImporter.textureType == TextureImporterType.GUI)
continue;
badTextures.Add(texture);
}
if (badTextures.Count == 0)
{
result.Status = TestResultStatus.Pass;
result.AddMessage("All texture dimensions are a power of 2!");
}
else
{
result.Status = TestResultStatus.VariableSeverityIssue;
result.AddMessage("The following texture dimensions are not a power of 2:", null, badTextures.ToArray());
}
return result;
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 073f1dacf3da34d4783140ae9d485d5f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 115
packageName: Asset Store Publishing Tools
packageVersion: 12.0.1
assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckTextureDimensions.cs
uploadId: 724584

View File

@@ -0,0 +1,233 @@
using AssetStoreTools.Validator.Data;
using AssetStoreTools.Validator.Services.Validation;
using AssetStoreTools.Validator.TestDefinitions;
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityObject = UnityEngine.Object;
namespace AssetStoreTools.Validator.TestMethods
{
internal class CheckTypeNamespaces : ITestScript
{
private readonly string[] ForbiddenNamespaces = new string[] { "Unity" };
private GenericTestConfig _config;
private IAssetUtilityService _assetUtility;
private IScriptUtilityService _scriptUtility;
private enum NamespaceEligibility
{
NoNamespace,
Ok,
Forbidden
}
private class AnalysisResult
{
public Dictionary<UnityObject, List<string>> TypesWithoutNamespaces;
public Dictionary<UnityObject, List<string>> ForbiddenNamespaces;
public bool HasIssues => TypesWithoutNamespaces.Count > 0
|| ForbiddenNamespaces.Count > 0;
}
public CheckTypeNamespaces(GenericTestConfig config, IAssetUtilityService assetUtility, IScriptUtilityService scriptUtility)
{
_config = config;
_assetUtility = assetUtility;
_scriptUtility = scriptUtility;
}
public TestResult Run()
{
var result = new TestResult() { Status = TestResultStatus.Undefined };
var scriptResult = CheckScripts();
var assemblyResult = CheckAssemblies();
if (scriptResult.HasIssues || assemblyResult.HasIssues)
{
result.Status = TestResultStatus.Warning;
// Error conditions for forbidden namespaces
if (scriptResult.ForbiddenNamespaces.Count > 0)
{
result.Status = TestResultStatus.Fail;
result.AddMessage("The following scripts contain namespaces starting with a 'Unity' keyword:");
AddJoinedMessage(result, scriptResult.ForbiddenNamespaces);
}
if (assemblyResult.ForbiddenNamespaces.Count > 0)
{
result.Status = TestResultStatus.Fail;
result.AddMessage("The following assemblies contain namespaces starting with a 'Unity' keyword:");
AddJoinedMessage(result, assemblyResult.ForbiddenNamespaces);
}
// Variable severity conditions for no-namespace types
if (scriptResult.TypesWithoutNamespaces.Count > 0)
{
if (result.Status != TestResultStatus.Fail)
result.Status = TestResultStatus.VariableSeverityIssue;
result.AddMessage("The following scripts contain types not nested under a namespace:");
AddJoinedMessage(result, scriptResult.TypesWithoutNamespaces);
}
if (assemblyResult.TypesWithoutNamespaces.Count > 0)
{
if (result.Status != TestResultStatus.Fail)
result.Status = TestResultStatus.VariableSeverityIssue;
result.AddMessage("The following assemblies contain types not nested under a namespace:");
AddJoinedMessage(result, assemblyResult.TypesWithoutNamespaces);
}
}
else
{
result.Status = TestResultStatus.Pass;
result.AddMessage("All scripts contain valid namespaces!");
}
return result;
}
private AnalysisResult CheckScripts()
{
var scripts = _assetUtility.GetObjectsFromAssets<MonoScript>(_config.ValidationPaths, AssetType.MonoScript).ToArray();
var scriptNamespaces = _scriptUtility.GetTypeNamespacesFromScriptAssets(scripts);
var scriptsWithoutNamespaces = new Dictionary<UnityObject, List<string>>();
var scriptsWithForbiddenNamespaces = new Dictionary<UnityObject, List<string>>();
foreach (var kvp in scriptNamespaces)
{
var scriptAsset = kvp.Key;
var typesInScriptAsset = kvp.Value;
var typesWithoutNamespace = new List<string>();
var discouragedNamespaces = new List<string>();
var forbiddenNamespaces = new List<string>();
foreach (var t in typesInScriptAsset)
{
var eligibility = CheckNamespaceEligibility(t.Namespace);
switch (eligibility)
{
case NamespaceEligibility.NoNamespace:
typesWithoutNamespace.Add(t.Name);
break;
case NamespaceEligibility.Forbidden:
if (!forbiddenNamespaces.Contains(t.Namespace))
forbiddenNamespaces.Add(t.Namespace);
break;
case NamespaceEligibility.Ok:
break;
}
}
if (typesWithoutNamespace.Count > 0)
scriptsWithoutNamespaces.Add(scriptAsset, typesWithoutNamespace);
if (forbiddenNamespaces.Count > 0)
scriptsWithForbiddenNamespaces.Add(scriptAsset, forbiddenNamespaces);
}
return new AnalysisResult
{
TypesWithoutNamespaces = scriptsWithoutNamespaces,
ForbiddenNamespaces = scriptsWithForbiddenNamespaces
};
}
private AnalysisResult CheckAssemblies()
{
var assemblies = _assetUtility.GetObjectsFromAssets(_config.ValidationPaths, AssetType.PrecompiledAssembly).ToList();
var assemblyTypes = _scriptUtility.GetTypesFromAssemblies(assemblies);
var assembliesWithoutNamespaces = new Dictionary<UnityObject, List<string>>();
var assembliesWithForbiddenNamespaces = new Dictionary<UnityObject, List<string>>();
foreach (var kvp in assemblyTypes)
{
var assemblyAsset = kvp.Key;
var typesInAssembly = kvp.Value;
var typesWithoutNamespace = new List<string>();
var discouragedNamespaces = new List<string>();
var forbiddenNamespaces = new List<string>();
foreach (var t in typesInAssembly)
{
var eligibility = CheckNamespaceEligibility(t.Namespace);
switch (eligibility)
{
case NamespaceEligibility.NoNamespace:
typesWithoutNamespace.Add($"{GetTypeName(t)} {t.Name}");
break;
case NamespaceEligibility.Forbidden:
if (!forbiddenNamespaces.Contains(t.Namespace))
forbiddenNamespaces.Add(t.Namespace);
break;
case NamespaceEligibility.Ok:
break;
}
}
if (typesWithoutNamespace.Count > 0)
assembliesWithoutNamespaces.Add(assemblyAsset, typesWithoutNamespace);
if (forbiddenNamespaces.Count > 0)
assembliesWithForbiddenNamespaces.Add(assemblyAsset, forbiddenNamespaces);
}
return new AnalysisResult
{
TypesWithoutNamespaces = assembliesWithoutNamespaces,
ForbiddenNamespaces = assembliesWithForbiddenNamespaces
};
}
private NamespaceEligibility CheckNamespaceEligibility(string fullNamespace)
{
if (string.IsNullOrEmpty(fullNamespace))
return NamespaceEligibility.NoNamespace;
var split = fullNamespace.Split('.');
var topLevelNamespace = split[0];
if (ForbiddenNamespaces.Any(x => topLevelNamespace.StartsWith(x, StringComparison.OrdinalIgnoreCase)))
return NamespaceEligibility.Forbidden;
return NamespaceEligibility.Ok;
}
private string GetTypeName(Type type)
{
if (type.IsClass)
return "class";
if (type.IsInterface)
return "interface";
if (type.IsEnum)
return "enum";
if (type.IsValueType)
return "struct";
throw new ArgumentException($"Received an unrecognizable type {type}. Type must be either a class, interface, struct or enum");
}
private void AddJoinedMessage(TestResult result, Dictionary<UnityObject, List<string>> assetsWithMessages)
{
foreach (var kvp in assetsWithMessages)
{
var message = string.Join("\n", kvp.Value);
result.AddMessage(message, null, kvp.Key);
}
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 279249fa7ef8c2446b3a9f013eeedbf0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 115
packageName: Asset Store Publishing Tools
packageVersion: 12.0.1
assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckTypeNamespaces.cs
uploadId: 724584

View File

@@ -0,0 +1,38 @@
using AssetStoreTools.Validator.Data;
using AssetStoreTools.Validator.Services.Validation;
using AssetStoreTools.Validator.TestDefinitions;
using System.Linq;
namespace AssetStoreTools.Validator.TestMethods
{
internal class RemoveExecutableFiles : ITestScript
{
private GenericTestConfig _config;
private IAssetUtilityService _assetUtility;
public RemoveExecutableFiles(GenericTestConfig config, IAssetUtilityService assetUtility)
{
_config = config;
_assetUtility = assetUtility;
}
public TestResult Run()
{
var result = new TestResult() { Status = TestResultStatus.Undefined };
var executables = _assetUtility.GetObjectsFromAssets(_config.ValidationPaths, AssetType.Executable).ToArray();
if (executables.Length == 0)
{
result.Status = TestResultStatus.Pass;
result.AddMessage("No executable files were found!");
return result;
}
result.Status = TestResultStatus.VariableSeverityIssue;
result.AddMessage("The following executable files were found", null, executables);
return result;
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 8e4450592cc60e54286ad089b66db94d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 115
packageName: Asset Store Publishing Tools
packageVersion: 12.0.1
assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveExecutableFiles.cs
uploadId: 724584

View File

@@ -0,0 +1,38 @@
using AssetStoreTools.Validator.Data;
using AssetStoreTools.Validator.Services.Validation;
using AssetStoreTools.Validator.TestDefinitions;
using System.Linq;
namespace AssetStoreTools.Validator.TestMethods
{
internal class RemoveJPGFiles : ITestScript
{
private GenericTestConfig _config;
private IAssetUtilityService _assetUtility;
public RemoveJPGFiles(GenericTestConfig config, IAssetUtilityService assetUtility)
{
_config = config;
_assetUtility = assetUtility;
}
public TestResult Run()
{
var result = new TestResult() { Status = TestResultStatus.Undefined };
var jpgs = _assetUtility.GetObjectsFromAssets(_config.ValidationPaths, AssetType.JPG).ToArray();
if (jpgs.Length == 0)
{
result.Status = TestResultStatus.Pass;
result.AddMessage("No JPG/JPEG textures were found!");
return result;
}
result.Status = TestResultStatus.VariableSeverityIssue;
result.AddMessage("The following textures are compressed as JPG/JPEG", null, jpgs);
return result;
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 5634a12b3a8544c4585bbc280ae59ce2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 115
packageName: Asset Store Publishing Tools
packageVersion: 12.0.1
assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveJPGFiles.cs
uploadId: 724584

View File

@@ -0,0 +1,38 @@
using AssetStoreTools.Validator.Data;
using AssetStoreTools.Validator.Services.Validation;
using AssetStoreTools.Validator.TestDefinitions;
using System.Linq;
namespace AssetStoreTools.Validator.TestMethods
{
internal class RemoveJavaScriptFiles : ITestScript
{
private GenericTestConfig _config;
private IAssetUtilityService _assetUtility;
public RemoveJavaScriptFiles(GenericTestConfig config, IAssetUtilityService assetUtility)
{
_config = config;
_assetUtility = assetUtility;
}
public TestResult Run()
{
var result = new TestResult() { Status = TestResultStatus.Undefined };
var javascriptObjects = _assetUtility.GetObjectsFromAssets(_config.ValidationPaths, AssetType.JavaScript).ToArray();
if (javascriptObjects.Length == 0)
{
result.Status = TestResultStatus.Pass;
result.AddMessage("No UnityScript / JS files were found!");
return result;
}
result.Status = TestResultStatus.VariableSeverityIssue;
result.AddMessage("The following assets are UnityScript / JS files", null, javascriptObjects);
return result;
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: ab1676bde9afba442b35fd3319c18063
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 115
packageName: Asset Store Publishing Tools
packageVersion: 12.0.1
assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveJavaScriptFiles.cs
uploadId: 724584

View File

@@ -0,0 +1,83 @@
using AssetStoreTools.Validator.Data;
using AssetStoreTools.Validator.Services.Validation;
using AssetStoreTools.Validator.TestDefinitions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using UnityObject = UnityEngine.Object;
namespace AssetStoreTools.Validator.TestMethods
{
internal class RemoveLossyAudioFiles : ITestScript
{
private GenericTestConfig _config;
private IAssetUtilityService _assetUtility;
public RemoveLossyAudioFiles(GenericTestConfig config, IAssetUtilityService assetUtility)
{
_config = config;
_assetUtility = assetUtility;
}
public TestResult Run()
{
var result = new TestResult() { Status = TestResultStatus.Undefined };
string SanitizeForComparison(UnityObject o)
{
Regex alphanumericRegex = new Regex("[^a-zA-Z0-9]");
string path = _assetUtility.ObjectToAssetPath(o);
path = path.ToLower();
int extensionIndex = path.LastIndexOf('.');
string extension = path.Substring(extensionIndex + 1);
string sanitized = path.Substring(0, extensionIndex);
int separatorIndex = sanitized.LastIndexOf('/');
sanitized = sanitized.Substring(separatorIndex);
sanitized = alphanumericRegex.Replace(sanitized, String.Empty);
sanitized = sanitized.Replace(extension, String.Empty);
sanitized = sanitized.Trim();
return sanitized;
}
var lossyAudioObjects = _assetUtility.GetObjectsFromAssets(_config.ValidationPaths, AssetType.LossyAudio).ToArray();
if (lossyAudioObjects.Length == 0)
{
result.Status = TestResultStatus.Pass;
result.AddMessage("No lossy audio files were found!");
return result;
}
// Try to find and match variants
var nonLossyAudioObjects = _assetUtility.GetObjectsFromAssets(_config.ValidationPaths, AssetType.NonLossyAudio);
HashSet<string> nonLossyPathSet = new HashSet<string>();
foreach (var asset in nonLossyAudioObjects)
{
var path = SanitizeForComparison(asset);
nonLossyPathSet.Add(path);
}
var unmatchedAssets = new List<UnityObject>();
foreach (var asset in lossyAudioObjects)
{
var path = SanitizeForComparison(asset);
if (!nonLossyPathSet.Contains(path))
unmatchedAssets.Add(asset);
}
if (unmatchedAssets.Count == 0)
{
result.Status = TestResultStatus.Pass;
result.AddMessage("No lossy audio files were found!");
return result;
}
result.Status = TestResultStatus.VariableSeverityIssue;
result.AddMessage("The following lossy audio files were found without identically named non-lossy variants:", null, unmatchedAssets.ToArray());
return result;
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: b7205a85061273a4eb50586f13f35d35
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 115
packageName: Asset Store Publishing Tools
packageVersion: 12.0.1
assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveLossyAudioFiles.cs
uploadId: 724584

View File

@@ -0,0 +1,38 @@
using AssetStoreTools.Validator.Data;
using AssetStoreTools.Validator.Services.Validation;
using AssetStoreTools.Validator.TestDefinitions;
using System.Linq;
namespace AssetStoreTools.Validator.TestMethods
{
internal class RemoveMixamoFiles : ITestScript
{
private GenericTestConfig _config;
private IAssetUtilityService _assetUtility;
public RemoveMixamoFiles(GenericTestConfig config, IAssetUtilityService assetUtility)
{
_config = config;
_assetUtility = assetUtility;
}
public TestResult Run()
{
var result = new TestResult() { Status = TestResultStatus.Undefined };
var mixamoFiles = _assetUtility.GetObjectsFromAssets(_config.ValidationPaths, AssetType.Mixamo).ToArray();
if (mixamoFiles.Length == 0)
{
result.Status = TestResultStatus.Pass;
result.AddMessage("No Mixamo files were found!");
return result;
}
result.Status = TestResultStatus.VariableSeverityIssue;
result.AddMessage("The following Mixamo files were found", null, mixamoFiles);
return result;
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 9df432e52aa958b44bb5e20c13d16552
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 115
packageName: Asset Store Publishing Tools
packageVersion: 12.0.1
assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveMixamoFiles.cs
uploadId: 724584

View File

@@ -0,0 +1,38 @@
using AssetStoreTools.Validator.Data;
using AssetStoreTools.Validator.Services.Validation;
using AssetStoreTools.Validator.TestDefinitions;
using System.Linq;
namespace AssetStoreTools.Validator.TestMethods
{
internal class RemoveSpeedTreeFiles : ITestScript
{
private GenericTestConfig _config;
private IAssetUtilityService _assetUtility;
public RemoveSpeedTreeFiles(GenericTestConfig config, IAssetUtilityService assetUtility)
{
_config = config;
_assetUtility = assetUtility;
}
public TestResult Run()
{
var result = new TestResult() { Status = TestResultStatus.Undefined };
var speedtreeObjects = _assetUtility.GetObjectsFromAssets(_config.ValidationPaths, AssetType.SpeedTree).ToArray();
if (speedtreeObjects.Length == 0)
{
result.Status = TestResultStatus.Pass;
result.AddMessage("No SpeedTree assets have been found!");
return result;
}
result.Status = TestResultStatus.VariableSeverityIssue;
result.AddMessage("The following SpeedTree assets have been found", null, speedtreeObjects);
return result;
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: e06bb7e0aa4f9944abc18281c002dff4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 115
packageName: Asset Store Publishing Tools
packageVersion: 12.0.1
assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveSpeedTreeFiles.cs
uploadId: 724584

View File

@@ -0,0 +1,38 @@
using AssetStoreTools.Validator.Data;
using AssetStoreTools.Validator.Services.Validation;
using AssetStoreTools.Validator.TestDefinitions;
using System.Linq;
namespace AssetStoreTools.Validator.TestMethods
{
internal class RemoveVideoFiles : ITestScript
{
private GenericTestConfig _config;
private IAssetUtilityService _assetUtility;
public RemoveVideoFiles(GenericTestConfig config, IAssetUtilityService assetUtility)
{
_config = config;
_assetUtility = assetUtility;
}
public TestResult Run()
{
var result = new TestResult() { Status = TestResultStatus.Undefined };
var videos = _assetUtility.GetObjectsFromAssets(_config.ValidationPaths, AssetType.Video).ToArray();
if (videos.Length == 0)
{
result.Status = TestResultStatus.Pass;
result.AddMessage("No video files were found, looking good!");
return result;
}
result.Status = TestResultStatus.VariableSeverityIssue;
result.AddMessage("The following video files were found", null, videos);
return result;
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: f99724c71b0de66419b5d6e8e9bfcc2d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 115
packageName: Asset Store Publishing Tools
packageVersion: 12.0.1
assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveVideoFiles.cs
uploadId: 724584

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 016d62b2cd8346a49815615efd1d6e39
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,172 @@
using AssetStoreTools.Validator.Data;
using AssetStoreTools.Validator.Services.Validation;
using AssetStoreTools.Validator.TestDefinitions;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEngine;
using UnityObject = UnityEngine.Object;
namespace AssetStoreTools.Validator.TestMethods
{
internal class CheckDemoScenes : ITestScript
{
private class DemoSceneScanResult
{
public List<UnityObject> ValidAdbScenes;
public List<string> HybridScenePaths;
public List<UnityObject> NestedUnityPackages;
}
private GenericTestConfig _config;
private IAssetUtilityService _assetUtility;
private ISceneUtilityService _sceneUtility;
public CheckDemoScenes(GenericTestConfig config, IAssetUtilityService assetUtility, ISceneUtilityService sceneUtility)
{
_config = config;
_assetUtility = assetUtility;
_sceneUtility = sceneUtility;
}
public TestResult Run()
{
var result = new TestResult();
var demoSceneScanResult = CheckForDemoScenes(_config);
// Valid demo scenes were found in ADB
if (demoSceneScanResult.ValidAdbScenes.Count > 0)
{
result.Status = TestResultStatus.Pass;
result.AddMessage("Demo scenes found", null, demoSceneScanResult.ValidAdbScenes.ToArray());
return result;
}
// Valid demo scenes found in UPM package.json
if (demoSceneScanResult.HybridScenePaths.Count > 0)
{
result.Status = TestResultStatus.Pass;
var upmSampleSceneList = string.Join("\n-", demoSceneScanResult.HybridScenePaths);
upmSampleSceneList = upmSampleSceneList.Insert(0, "-");
result.AddMessage($"Demo scenes found:\n{upmSampleSceneList}");
return result;
}
// No valid scenes found, but package contains nested .unitypackages
if (demoSceneScanResult.NestedUnityPackages.Count > 0)
{
result.Status = TestResultStatus.Warning;
result.AddMessage("Could not find any valid Demo scenes in the selected validation paths.");
result.AddMessage("The following nested .unitypackage files were found. " +
"If they contain any demo scenes, you can ignore this warning.", null, demoSceneScanResult.NestedUnityPackages.ToArray());
return result;
}
// No valid scenes were found and there is nothing pointing to their inclusion in the package
result.Status = TestResultStatus.VariableSeverityIssue;
result.AddMessage("Could not find any valid Demo Scenes in the selected validation paths.");
return result;
}
private DemoSceneScanResult CheckForDemoScenes(GenericTestConfig config)
{
var scanResult = new DemoSceneScanResult();
scanResult.ValidAdbScenes = CheckForDemoScenesInAssetDatabase(config);
scanResult.HybridScenePaths = CheckForDemoScenesInUpmSamples(config);
scanResult.NestedUnityPackages = CheckForNestedUnityPackages(config);
return scanResult;
}
private List<UnityObject> CheckForDemoScenesInAssetDatabase(GenericTestConfig config)
{
var scenePaths = _assetUtility.GetAssetPathsFromAssets(config.ValidationPaths, AssetType.Scene).ToArray();
if (scenePaths.Length == 0)
return new List<UnityObject>();
var originalScenePath = _sceneUtility.CurrentScenePath;
var validScenePaths = scenePaths.Where(CanBeDemoScene).ToArray();
_sceneUtility.OpenScene(originalScenePath);
if (validScenePaths.Length == 0)
return new List<UnityObject>();
return validScenePaths.Select(x => AssetDatabase.LoadAssetAtPath<UnityObject>(x)).ToList();
}
private bool CanBeDemoScene(string scenePath)
{
// Check skybox
var sceneSkyboxPath = _assetUtility.ObjectToAssetPath(RenderSettings.skybox).Replace("\\", "").Replace("/", "");
var defaultSkyboxPath = "Resources/unity_builtin_extra".Replace("\\", "").Replace("/", "");
if (!sceneSkyboxPath.Equals(defaultSkyboxPath, StringComparison.OrdinalIgnoreCase))
return true;
// Check GameObjects
_sceneUtility.OpenScene(scenePath);
var rootObjects = _sceneUtility.GetRootGameObjects();
var count = rootObjects.Length;
if (count == 0)
return false;
if (count != 2)
return true;
var cameraGOUnchanged = rootObjects.Any(o => o.TryGetComponent<Camera>(out _) && o.GetComponents(typeof(Component)).Length == 3);
var lightGOUnchanged = rootObjects.Any(o => o.TryGetComponent<Light>(out _) && o.GetComponents(typeof(Component)).Length == 2);
return !cameraGOUnchanged || !lightGOUnchanged;
}
private List<string> CheckForDemoScenesInUpmSamples(GenericTestConfig config)
{
var scenePaths = new List<string>();
foreach (var path in config.ValidationPaths)
{
if (!File.Exists($"{path}/package.json"))
continue;
var packageJsonText = File.ReadAllText($"{path}/package.json");
var json = JObject.Parse(packageJsonText);
if (!json.ContainsKey("samples") || json["samples"].Type != JTokenType.Array || json["samples"].ToList().Count == 0)
continue;
foreach (var sample in json["samples"].ToList())
{
var samplePath = sample["path"].ToString();
samplePath = $"{path}/{samplePath}";
if (!Directory.Exists(samplePath))
continue;
var sampleScenePaths = Directory.GetFiles(samplePath, "*.unity", SearchOption.AllDirectories);
foreach (var scenePath in sampleScenePaths)
{
// If meta file is not found, the sample will not be included with the exported .unitypackage
if (!File.Exists($"{scenePath}.meta"))
continue;
if (!scenePaths.Contains(scenePath.Replace("\\", "/")))
scenePaths.Add(scenePath.Replace("\\", "/"));
}
}
}
return scenePaths;
}
private List<UnityObject> CheckForNestedUnityPackages(GenericTestConfig config)
{
var unityPackages = _assetUtility.GetObjectsFromAssets(config.ValidationPaths, AssetType.UnityPackage).ToArray();
return unityPackages.ToList();
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: f844c2dfa4669ff4eacf5591b544edaf
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 115
packageName: Asset Store Publishing Tools
packageVersion: 12.0.1
assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/UnityPackage/CheckDemoScenes.cs
uploadId: 724584

View File

@@ -0,0 +1,73 @@
using AssetStoreTools.Validator.Data;
using AssetStoreTools.Validator.Services.Validation;
using AssetStoreTools.Validator.TestDefinitions;
using System;
using System.IO;
using System.Linq;
namespace AssetStoreTools.Validator.TestMethods
{
internal class CheckDocumentation : ITestScript
{
private GenericTestConfig _config;
private IAssetUtilityService _assetUtility;
public CheckDocumentation(GenericTestConfig config, IAssetUtilityService assetUtility)
{
_config = config;
_assetUtility = assetUtility;
}
public TestResult Run()
{
var result = new TestResult() { Status = TestResultStatus.Undefined };
var textFilePaths = _assetUtility.GetAssetPathsFromAssets(_config.ValidationPaths, AssetType.Documentation).ToArray();
var documentationFilePaths = textFilePaths.Where(CouldBeDocumentation).ToArray();
if (textFilePaths.Length == 0)
{
result.Status = TestResultStatus.VariableSeverityIssue;
result.AddMessage("No potential documentation files ('.txt', '.pdf', " +
"'.html', '.rtf', '.md') found within the given path.");
}
else if (documentationFilePaths.Length == 0)
{
result.Status = TestResultStatus.Warning;
var textFileObjects = textFilePaths.Select(_assetUtility.AssetPathToObject).ToArray();
result.AddMessage("The following files have been found to match the documentation file format," +
" but may not be documentation in content",
null, textFileObjects);
}
else
{
result.Status = TestResultStatus.Pass;
var documentationFileObjects = documentationFilePaths.Select(_assetUtility.AssetPathToObject).ToArray();
result.AddMessage("Found documentation files", null, documentationFileObjects);
}
return result;
}
private bool CouldBeDocumentation(string filePath)
{
if (filePath.EndsWith(".pdf"))
return true;
using (var fs = File.Open(filePath, FileMode.Open))
using (var bs = new BufferedStream(fs))
using (var sr = new StreamReader(bs))
{
string line;
while ((line = sr.ReadLine()) != null)
{
var mentionsDocumentation = line.IndexOf("documentation", StringComparison.OrdinalIgnoreCase) >= 0;
if (mentionsDocumentation)
return true;
}
}
return false;
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 3c8425198983eda4c9b35aa0d59ea33c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 115
packageName: Asset Store Publishing Tools
packageVersion: 12.0.1
assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/UnityPackage/CheckDocumentation.cs
uploadId: 724584

View File

@@ -0,0 +1,69 @@
using AssetStoreTools.Validator.Data;
using AssetStoreTools.Validator.TestDefinitions;
using System.IO;
namespace AssetStoreTools.Validator.TestMethods
{
internal class CheckPackageSize : ITestScript
{
private GenericTestConfig _config;
public CheckPackageSize(GenericTestConfig config)
{
_config = config;
}
public TestResult Run()
{
var result = new TestResult() { Status = TestResultStatus.Undefined };
var packageSize = CalculatePackageSize(_config.ValidationPaths);
float packageSizeInGB = packageSize / (1024f * 1024f * 1024f);
float maxPackageSizeInGB = Constants.Uploader.MaxPackageSizeBytes / (1024f * 1024f * 1024f);
if (packageSizeInGB - maxPackageSizeInGB >= 0.1f)
{
result.Status = TestResultStatus.Warning;
result.AddMessage($"The uncompressed size of your package ({packageSizeInGB:0.#} GB) exceeds the maximum allowed package size of {maxPackageSizeInGB:0.#} GB. " +
$"Please make sure that the compressed .unitypackage size does not exceed the size limit.");
}
else
{
result.Status = TestResultStatus.Pass;
result.AddMessage("Your package does not exceed the maximum allowed package size!");
}
return result;
}
private long CalculatePackageSize(string[] assetPaths)
{
long totalSize = 0;
foreach (var path in assetPaths)
{
totalSize += CalculatePathSize(path);
}
return totalSize;
}
private long CalculatePathSize(string path)
{
long size = 0;
var dirInfo = new DirectoryInfo(path);
if (!dirInfo.Exists)
return size;
foreach (var file in dirInfo.EnumerateFiles())
size += file.Length;
foreach (var nestedDir in dirInfo.EnumerateDirectories())
size += CalculatePathSize(nestedDir.FullName);
return size;
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: a8601b99f4afa5049954f3a2dd5996d6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 115
packageName: Asset Store Publishing Tools
packageVersion: 12.0.1
assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/UnityPackage/CheckPackageSize.cs
uploadId: 724584

View File

@@ -0,0 +1,217 @@
using AssetStoreTools.Validator.Data;
using AssetStoreTools.Validator.Services.Validation;
using AssetStoreTools.Validator.TestDefinitions;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
namespace AssetStoreTools.Validator.TestMethods
{
internal class CheckProjectTemplateAssets : ITestScript
{
private GenericTestConfig _config;
private IAssetUtilityService _assetUtility;
// Constructor also accepts dependency injection of registered IValidatorService types
public CheckProjectTemplateAssets(GenericTestConfig config, IAssetUtilityService assetUtility)
{
_config = config;
_assetUtility = assetUtility;
}
public TestResult Run()
{
var result = new TestResult() { Status = TestResultStatus.Undefined };
var assets = _assetUtility.GetObjectsFromAssets<Object>(_config.ValidationPaths, AssetType.All);
var invalidAssetsByGuid = CheckGuids(assets);
var invalidAssetsByPath = CheckPaths(assets);
var hasIssues = invalidAssetsByGuid.Length > 0
|| invalidAssetsByPath.Length > 0;
if (hasIssues)
{
result.Status = TestResultStatus.VariableSeverityIssue;
if (invalidAssetsByPath.Length > 0)
{
result.AddMessage("The following assets were found to have an asset path which is common to project template asset paths. They should be renamed or moved:", null, invalidAssetsByPath);
}
if (invalidAssetsByGuid.Length > 0)
{
result.AddMessage("The following assets were found to be using a GUID which is common to project template asset GUIDs. They should be assigned a new GUID:", null, invalidAssetsByGuid);
}
}
else
{
result.Status = TestResultStatus.Pass;
result.AddMessage("No common assets that might cause asset clashing were found!");
}
return result;
}
private Object[] CheckGuids(IEnumerable<Object> assets)
{
var clashingAssets = new List<Object>();
foreach (var asset in assets)
{
if (!AssetDatabase.TryGetGUIDAndLocalFileIdentifier(asset, out var guid, out long _))
continue;
if (CommonTemplateAssets.Any(x => x.Key.Equals(guid, System.StringComparison.OrdinalIgnoreCase)))
clashingAssets.Add(asset);
}
return clashingAssets.ToArray();
}
private Object[] CheckPaths(IEnumerable<Object> assets)
{
var clashingAssets = new List<Object>();
foreach (var asset in assets)
{
var assetPath = AssetDatabase.GetAssetPath(asset);
if (CommonTemplateAssets.Any(x => x.Value.Equals(assetPath, System.StringComparison.OrdinalIgnoreCase)))
clashingAssets.Add(asset);
}
return clashingAssets.ToArray();
}
private Dictionary<string, string> CommonTemplateAssets = new Dictionary<string, string>()
{
{"3f9215ea0144899419cfbc0957140d3f", "Assets/DefaultVolumeProfile.asset"},
{"3d4c13846a3e9bd4c8ccfbd0657ed847", "Assets/DefaultVolumeProfile.asset"},
{"4cee8bca36f2ab74b8feb832747fa6f4", "Assets/Editor/com.unity.mobile.notifications/NotificationSettings.asset"},
{"45a04f37e0f48c744acc0874c4a8918a", "Assets/Editor/com.unity.mobile.notifications/NotificationSettings.asset"},
{"54a3a0570aebe8949bec4966f1376581", "Assets/HDRPDefaultResources/DefaultHDRISky.exr"},
{"e93c35b24eb03c74284e7dc0b755bfcc", "Assets/HDRPDefaultResources/DefaultHDRPAsset.asset"},
{"254320a857a30444da2c99496a186368", "Assets/HDRPDefaultResources/DefaultLookDevProfile.asset"},
{"2bfa7b9d63fa79e4abdc033f54a868d2", "Assets/HDRPDefaultResources/DefaultSceneRoot.prefab"},
{"f9e3ff5a1b8f49c4fa8686e68d2dadae", "Assets/HDRPDefaultResources/DefaultSceneRoot.prefab"},
{"d87f7d7815073e840834a16a518c1237", "Assets/HDRPDefaultResources/DefaultSettingsVolumeProfile.asset"},
{"145290c901d58b343bdeb3b4362c9ff2", "Assets/HDRPDefaultResources/DefaultVFXResources.asset"},
{"acc11144f57719542b5fa25f02e74afb", "Assets/HDRPDefaultResources/HDRenderPipelineGlobalSettings.asset"},
{"582adbd84082fdb4faf7cd4beb1ccd14", "Assets/HDRPDefaultResources/HDRPDefaultSettings.asset"},
{"2801c2ff7303a7543a8727f862f6c236", "Assets/HDRPDefaultResources/Sky and Fog Settings Profile.asset"},
{"ea5c25297f0c0a04da0eabb1c26a7509", "Assets/HDRPDefaultResources/SkyFogSettingsProfile.asset"},
{"3590b91b4603b465dbb4216d601bff33", "Assets/InputSystem_Actions.inputactions"},
{"289c1b55c9541489481df5cc06664110", "Assets/InputSystem_Actions.inputactions"},
{"dc70d2c4f369241dd99afd7c451b813e", "Assets/InputSystem_Actions.inputactions"},
{"2bcd2660ca9b64942af0de543d8d7100", "Assets/InputSystem_Actions.inputactions"},
{"052faaac586de48259a63d0c4782560b", "Assets/InputSystem_Actions.inputactions"},
{"35845fe01580c41289b024647b1d1c53", "Assets/InputSystem_Actions.inputactions"},
{"8124e5870f4fd4c779e7a5f994e84ad1", "Assets/OutdoorsScene.unity"},
{"2dd802e4d37c65149922028d3e973832", "Assets/Presets/AudioCompressedInMemory.preset"},
{"e18fd6ecd9cdb524ca99844f39b9d9ac", "Assets/Presets/AudioCompressedInMemory.preset"},
{"86bcce7f5575b54408aa0f3a7d321039", "Assets/Presets/AudioStreaming.preset"},
{"460e573eb8466884baaa0b8475505f83", "Assets/Presets/AudioStreaming.preset"},
{"e8537455c6c08bd4e8bf0be3707da685", "Assets/Presets/Defaults/AlbedoTexture_Default.preset"},
{"7a99f8aa944efe94cb9bd74562b7d5f9", "Assets/Presets/Defaults/AlbedoTexture_Default.preset"},
{"0cd792cc87e492d43b4e95b205fc5cc6", "Assets/Presets/Defaults/AudioDecompressOnLoad_Default.preset"},
{"e7689051185d12f4298e1ebb2693a29f", "Assets/Presets/Defaults/AudioDecompressOnLoad.preset"},
{"463065d4f17d1d94d848aa127b94dd43", "Assets/Presets/Defaults/DirectionalLight_Default.preset"},
{"c1cf8506f04ef2c4a88b64b6c4202eea", "Assets/Presets/Defaults/DirectionalLight_Default.preset"},
{"8fa3055e2a1363246838debd20206d37", "Assets/Presets/Defaults/SSSSettings_Default.preset"},
{"78830bb1431cab940b74be615e2a739f", "Assets/Presets/HDRTexture.preset"},
{"14a57cf3b9fa1c74b884aa7e0dcf1faa", "Assets/Presets/NormalTexture.preset"},
{"1d826a4c23450f946b19c20560595a1f", "Assets/Presets/NormalTexture.preset"},
{"45f7b2e3c78185248b3adbb14429c2ab", "Assets/Presets/UtilityTexture.preset"},
{"78fae3569c6c66c46afc3d9d4fb0b8d4", "Assets/Presets/UtilityTexture.preset"},
{"9303d565bd8aa6948ba775e843320e4d", "Assets/Presets/UtilityTexture.preset"},
{"34f54ff1ff9415249a847506b6f2fec5", "Assets/Scenes/PrefabEditingScene.unity"},
{"cbfe36cfddfde964d9dfce63a355d5dd", "Assets/Scenes/samplescene.unity"},
{"2cda990e2423bbf4892e6590ba056729", "Assets/Scenes/SampleScene.unity"},
{"9fc0d4010bbf28b4594072e72b8655ab", "Assets/Scenes/SampleScene.unity"},
{"3db1837cc97a95e4c98610966fac2b0b", "Assets/Scenes/SampleScene.unity"},
{"3fc8acdd13e6c734bafef6554d6fdbcd", "Assets/Scenes/SampleScene.unity"},
{"8c9cfa26abfee488c85f1582747f6a02", "Assets/Scenes/SampleScene.unity"},
{"c850ee8c3b14cc8459e7e186857cf567", "Assets/Scenes/SampleScene.unity"},
{"99c9720ab356a0642a771bea13969a05", "Assets/Scenes/SampleScene.unity"},
{"d1c3109bdb54ad54c8a2b2838528e640", "Assets/Scenes/SampleScene.unity"},
{"477cc4148fad3449482a3bc3178594e2", "Assets/Scenes/SampleSceneLightingSettings.lighting"},
{"4eb578550bc4f824e97f0a72eac1f3a5", "Assets/Scripts/LookWithMouse.cs"},
{"87f6dfceb3e39a947a312f7eeaa2a113", "Assets/Scripts/PlayerMovement.cs"},
{"be76e5f14cfee674cb30b491fb72b09b", "Assets/Scripts/SimpleCameraController.cs"},
{"6547d18b2bc62c94aa5ec1e87434da4e", "Assets/Scripts/SimpleCameraController.cs"},
{"e8a636f62116c0a40bbfefdf876d4608", "Assets/Scripts/SimpleCameraController.cs"},
{"14e519c409be4a1428028347410f5677", "Assets/Scripts/SimpleCameraController.cs"},
{"a04c28107d77d5e42b7155783b8475b6", "Assets/Settings/Cockpit_Renderer.asset"},
{"ab09877e2e707104187f6f83e2f62510", "Assets/Settings/DefaultVolumeProfile.asset"},
{"238cd62f6b58cb04e9c94749c4a015a7", "Assets/Settings/DefaultVolumeProfile.asset"},
{"5a9a2dc462c7bde4f86d0615a19c2c72", "Assets/Settings/DiffusionProfiles/BambooLeaves.asset"},
{"78322c7f82657514ebe48203160e3f39", "Assets/Settings/Foliage.asset"},
{"3e2e6bfc59709614ab90c0cd7d755e48", "Assets/Settings/HDRP Balanced.asset"},
{"36dd385e759c96147b6463dcd1149c11", "Assets/Settings/HDRP High Fidelity.asset"},
{"168a2336534e4e043b2a210b6f8d379a", "Assets/Settings/HDRP Performant.asset"},
{"4594f4a3fb14247e192bcca6dc23c8ed", "Assets/Settings/HDRPDefaultResources/DefaultLookDevProfile.asset"},
{"14b392ee213d25a48b1feddbd9f5a9be", "Assets/Settings/HDRPDefaultResources/DefaultSettingsVolumeProfile.asset"},
{"879ffae44eefa4412bb327928f1a96dd", "Assets/Settings/HDRPDefaultResources/FoliageDiffusionProfile.asset"},
{"b9f3086da92434da0bc1518f19f0ce86", "Assets/Settings/HDRPDefaultResources/HDRenderPipelineAsset.asset"},
{"ac0316ca287ba459492b669ff1317a6f", "Assets/Settings/HDRPDefaultResources/HDRenderPipelineGlobalSettings.asset"},
{"48e911a1e337b44e2b85dbc65b47a594", "Assets/Settings/HDRPDefaultResources/SkinDiffusionProfile.asset"},
{"d03ed43fc9d8a4f2e9fa70c1c7916eb9", "Assets/Settings/Lit2DSceneTemplate.scenetemplate"},
{"65bc7dbf4170f435aa868c779acfb082", "Assets/Settings/Mobile_Renderer.asset"},
{"5e6cbd92db86f4b18aec3ed561671858", "Assets/Settings/Mobile_RPAsset.asset"},
{"23cccccf13c3d4170a9b21e52a9bc86b", "Assets/Settings/Mobile/Mobile_High_ScreenRenderer.asset"},
{"6e8f76111115f44e0a76c2bff3cec258", "Assets/Settings/Mobile/Mobile_Low_Renderer.asset"},
{"aed30aee6a3ceae4090dadd1934d2ad0", "Assets/Settings/Mobile/Mobile_Low_ScreenRenderer.asset"},
{"d7686b11d09df481bac3c76ecc5ea626", "Assets/Settings/Mobile/Mobile_Low.asset"},
{"f288ae1f4751b564a96ac7587541f7a2", "Assets/Settings/PC_Renderer.asset"},
{"4b83569d67af61e458304325a23e5dfd", "Assets/Settings/PC_RPAsset.asset"},
{"42b230d443c6d6c4b89c47f97db59121", "Assets/Settings/PC/PC_High_ScreenRenderer.asset"},
{"13ba41cd2fa191f43890b271bd110ed9", "Assets/Settings/PC/PC_Low_Renderer.asset"},
{"a73f6fa069dd14a42b40cbb01bae63b4", "Assets/Settings/PC/PC_Low_ScreenRenderer.asset"},
{"4eb9ff6b5314098428cfa0be7e36ccda", "Assets/Settings/PC/PC_Low.asset"},
{"573ac53c334415945bf239de2c2f0511", "Assets/Settings/PlayerControllerFPS.prefab"},
{"7ba2b06fb32e5274aad88925a5b8d3f5", "Assets/Settings/PostProcessVolumeProfile.asset"},
{"424799608f7334c24bf367e4bbfa7f9a", "Assets/Settings/Renderer2D.asset"},
{"183cbd347d25080429f42b520742bbd8", "Assets/Settings/SampleScenePostProcessingSettings.asset"},
{"10fc4df2da32a41aaa32d77bc913491c", "Assets/Settings/SampleSceneProfile.asset"},
{"a6560a915ef98420e9faacc1c7438823", "Assets/Settings/SampleSceneProfile.asset"},
{"a123fc0ac58cb774e8592c925f167e7c", "Assets/Settings/SampleSceneSkyandFogSettings.asset"},
{"26bdddf49760c61438938733f07fa2a2", "Assets/Settings/Skin.asset"},
{"8ba92e2dd7f884a0f88b98fa2d235fe7", "Assets/Settings/SkyandFogSettingsProfile.asset"},
{"4a8e21d5c33334b11b34a596161b9360", "Assets/Settings/UniversalRenderer.asset"},
{"18dc0cd2c080841dea60987a38ce93fa", "Assets/Settings/UniversalRenderPipelineGlobalSettings.asset"},
{"bdede76083021864d8ff8bf23b2f37f1", "Assets/Settings/UniversalRenderPipelineGlobalSettings.asset"},
{"19ba41d7c0026c3459d37c2fe90c55a0", "Assets/Settings/UniversalRP-HighQuality.asset"},
{"a31e9f9f9c9d4b9429ed0d1234e22103", "Assets/Settings/UniversalRP-LowQuality.asset"},
{"d847b876476d3d6468f5dfcd34266f96", "Assets/Settings/UniversalRP-MediumQuality.asset"},
{"681886c5eb7344803b6206f758bf0b1c", "Assets/Settings/UniversalRP.asset"},
{"e634585d5c4544dd297acaee93dc2beb", "Assets/Settings/URP-Balanced-Renderer.asset"},
{"e1260c1148f6143b28bae5ace5e9c5d1", "Assets/Settings/URP-Balanced.asset"},
{"c40be3174f62c4acf8c1216858c64956", "Assets/Settings/URP-HighFidelity-Renderer.asset"},
{"7b7fd9122c28c4d15b667c7040e3b3fd", "Assets/Settings/URP-HighFidelity.asset"},
{"707360a9c581a4bd7aa53bfeb1429f71", "Assets/Settings/URP-Performant-Renderer.asset"},
{"d0e2fc18fe036412f8223b3b3d9ad574", "Assets/Settings/URP-Performant.asset"},
{"b62413aeefabaaa41a4b5a71dd7ae1ac", "Assets/Settings/VolumeProfiles/CinematicProfile.asset"},
{"ac0c2cad5778d4544b6a690963e02fe3", "Assets/Settings/VolumeProfiles/DefaultVolumeProfile.asset"},
{"f2d4d916a6612574cad220d125febbf2", "Assets/Settings/VolumeProfiles/LowQualityVolumeProfile.asset"},
{"cef078630d63d0442a070f84d4f13735", "Assets/Settings/VolumeProfiles/MarketProfile.asset"},
{"7ede9c9f109e5c442b7d29e54b4996fc", "Assets/Settings/VolumeProfiles/MediaOverrides.asset"},
{"3532e98caae428047bcefe69a344f72c", "Assets/Settings/VolumeProfiles/OutlineEnabled.asset"},
{"bfc08ba7e35de1a44bb84a32f1a693e1", "Assets/Settings/VolumeProfiles/ZenGardenProfile.asset"},
{"59a34a3881431c246b3564a0f0ca5bb0", "Assets/Settings/Volumes/CinematicPhysicalCamera.asset"},
{"03bc34b71695890468eb021c73b228db", "Assets/Settings/Volumes/ScreenshotsTimelineProfile.asset"},
{"7f342610b85f4164f808a1f380dcc668", "Assets/Settings/Volumes/VolumeGlobal.asset"},
{"bd6d234073408c44ca3828113aac655e", "Assets/Settings/Volumes/VolumeRoom1.asset"},
{"d78a1b031ab26034eb6ec3cbc9fbcec3", "Assets/Settings/Volumes/VolumeRoom2.asset"},
{"5727d3e07f75c3744b6cc8a1e55850a9", "Assets/Settings/Volumes/VolumeRoom2Skylight.asset"},
{"06114ad16a0bc0a41957375ac3bf472e", "Assets/Settings/Volumes/VolumeRoom3.asset"},
{"1584bf21cf81d5147aa00e8a2deaf2fb", "Assets/Settings/Volumes/VolumeRoom3Corridor.asset"},
{"7bca3a07cdd522c4c8020832c20b3eae", "Assets/Settings/Volumes/VolumeRoom3Sitting.asset"},
{"2872d90954412244a8b4a477b939c3ca", "Assets/Settings/XR/Loaders/Mock_HMD_Loader.asset"},
{"f25758a0f79593d4a9b3ee30a17b4c2e", "Assets/Settings/XR/Loaders/Oculus_Loader.asset"},
{"9e9f2958d1b4b4642ace1d0c7770650b", "Assets/Settings/XR/Settings/Mock_HMD_Build_Settings.asset"},
{"290a6e6411d135049940bec2237b8938", "Assets/Settings/XR/Settings/Oculus_Settings.asset"},
{"4c1640683c539c14080cfd43fbeffbda", "Assets/Settings/XR/XRGeneralSettings.asset"},
{"93b439a37f63240aca3dd4e01d978a9f", "Assets/UniversalRenderPipelineGlobalSettings.asset"},
{"38b35347542e5af4c9b140950c5b18db", "Assets/UniversalRenderPipelineGlobalSettings.asset"}
};
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: f02d52a702c712e4e8089f7c2e65bae7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 115
packageName: Asset Store Publishing Tools
packageVersion: 12.0.1
assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/UnityPackage/CheckProjectTemplateAssets.cs
uploadId: 724584