├── .gitignore ├── LICENSE ├── Packages ├── TextureHunter │ ├── Editor.meta │ ├── Editor │ │ ├── TextureHunter.Editor.asmdef │ │ ├── TextureHunter.Editor.asmdef.meta │ │ ├── TextureHunter.cs │ │ └── TextureHunter.cs.meta │ ├── LICENSE │ ├── LICENSE.meta │ ├── README.md │ ├── README.md.meta │ ├── package.json │ └── package.json.meta ├── manifest.json └── packages-lock.json ├── ProjectSettings ├── AudioManager.asset ├── ClusterInputManager.asset ├── DynamicsManager.asset ├── EditorBuildSettings.asset ├── EditorSettings.asset ├── GraphicsSettings.asset ├── InputManager.asset ├── NavMeshAreas.asset ├── NetworkManager.asset ├── PackageManagerSettings.asset ├── Physics2DSettings.asset ├── PresetManager.asset ├── ProjectSettings.asset ├── ProjectVersion.txt ├── QualitySettings.asset ├── TagManager.asset ├── TimeManager.asset ├── UnityConnectSettings.asset ├── VFXManager.asset ├── VersionControlSettings.asset └── XRSettings.asset ├── README.md ├── Screenshots ├── atlases_screen.png └── textures_screen.png └── UserSettings └── EditorUserSettings.asset /.gitignore: -------------------------------------------------------------------------------- 1 | # This .gitignore file should be placed at the root of your Unity project directory 2 | # 3 | # Get latest from https://github.com/github/gitignore/blob/master/Unity.gitignore 4 | # 5 | /[Ll]ibrary/ 6 | /[Tt]emp/ 7 | /[Oo]bj/ 8 | /[Bb]uild/ 9 | /[Bb]uilds/ 10 | /[Ll]ogs/ 11 | /[Uu]ser[Ss]ettings/ 12 | */[Oo]bj/* 13 | 14 | # MemoryCaptures can get excessive in size. 15 | # They also could contain extremely sensitive data 16 | /[Mm]emoryCaptures/ 17 | 18 | # Asset meta data should only be ignored when the corresponding asset is also ignored 19 | !/[Aa]ssets/**/*.meta 20 | 21 | # Uncomment this line if you wish to ignore the asset store tools plugin 22 | # /[Aa]ssets/AssetStoreTools* 23 | 24 | # Autogenerated Jetbrains Rider plugin 25 | /[Aa]ssets/Plugins/Editor/JetBrains* 26 | 27 | # Visual Studio cache directory 28 | .vs/ 29 | 30 | # Gradle cache directory 31 | .gradle/ 32 | 33 | # Jetbrains Rider cache directory 34 | .idea/ 35 | 36 | # Autogenerated VS/MD/Consulo solution and project files 37 | ExportedObj/ 38 | .consulo/ 39 | *.csproj 40 | *.unityproj 41 | *.sln 42 | *.suo 43 | *.tmp 44 | *.user 45 | *.userprefs 46 | *.pidb 47 | *.booproj 48 | *.svd 49 | *.pdb 50 | *.mdb 51 | *.opendb 52 | *.VC.db 53 | 54 | # Unity3D generated meta files 55 | *.pidb.meta 56 | *.pdb.meta 57 | *.mdb.meta 58 | 59 | # Unity3D generated file on crash reports 60 | sysinfo.txt 61 | 62 | # Builds 63 | *.apk 64 | *.unitypackage 65 | 66 | # Crashlytics generated file 67 | crashlytics-build.properties 68 | 69 | # Packed Addressables 70 | /[Aa]ssets/[Aa]ddressable[Aa]ssets[Dd]ata/*/*.bin* 71 | 72 | # Temporary auto-generated Android Assets 73 | /[Aa]ssets/[Ss]treamingAssets/aa.meta 74 | /[Aa]ssets/[Ss]treamingAssets/aa/* 75 | 76 | # Exceptions 77 | !*.dll 78 | !*.obj 79 | 80 | # Archives 81 | *.zip 82 | *.rar 83 | # Archives' meta files 84 | *.zip.meta 85 | *.rar.meta 86 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Alexey Perov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Packages/TextureHunter/Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 427bed4cee004e54fbd9dac8db64ae36 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Packages/TextureHunter/Editor/TextureHunter.Editor.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "TextureHunter.Editor", 3 | "references": [], 4 | "includePlatforms": [ 5 | "Editor" 6 | ], 7 | "excludePlatforms": [], 8 | "allowUnsafeCode": false, 9 | "overrideReferences": false, 10 | "precompiledReferences": [], 11 | "autoReferenced": true, 12 | "defineConstraints": [], 13 | "versionDefines": [], 14 | "noEngineReferences": false 15 | } -------------------------------------------------------------------------------- /Packages/TextureHunter/Editor/TextureHunter.Editor.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0bbde703baa0f41328a4cd00c5d14880 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Packages/TextureHunter/Editor/TextureHunter.cs: -------------------------------------------------------------------------------- 1 | // #define HUNT_ADDRESSABLES 2 | 3 | using System; 4 | using System.Collections; 5 | using System.Collections.Generic; 6 | using System.IO; 7 | using System.Linq; 8 | using System.Text; 9 | using System.Text.RegularExpressions; 10 | using UnityEditor; 11 | using UnityEditor.U2D; 12 | using UnityEngine; 13 | using UnityEngine.U2D; 14 | #if HUNT_ADDRESSABLES 15 | using UnityEditor.AddressableAssets; 16 | #endif 17 | 18 | // ReSharper disable once CheckNamespace 19 | namespace TextureHunter 20 | { 21 | public class TextureHunterWindow : EditorWindow 22 | { 23 | private class Result 24 | { 25 | public List Atlases { get; } = new List(); 26 | public List Textures { get; } = new List(); 27 | public string OutputDescription { get; set; } 28 | } 29 | 30 | private class AnalysisSettings 31 | { 32 | public const int DefaultGCStep = 100000; 33 | 34 | public bool MipMapsAreErrors { get; set; } = true; 35 | public bool ReadableAreErrors { get; set; } 36 | public bool SizeHigher4KAreErrors { get; set; } = true; 37 | public bool NoOverridenCompressionAsErrors { get; set; } = true; 38 | public int GarbageCollectStep { get; set; } = DefaultGCStep; 39 | 40 | // limit number of assets in analysis to perform it faster for debug purposes 41 | public int DebugLimit; 42 | 43 | public List RecommendedFormats { get; set; } = new List 44 | { 45 | TextureImporterFormat.ASTC_5x5, 46 | TextureImporterFormat.ASTC_6x6, 47 | TextureImporterFormat.ASTC_8x8, 48 | TextureImporterFormat.ASTC_10x10, 49 | TextureImporterFormat.ASTC_12x12, 50 | TextureImporterFormat.ETC2_RGBA8Crunched 51 | }; 52 | } 53 | 54 | private class SearchPatternsSettings 55 | { 56 | // ReSharper disable once StringLiteralTypo 57 | public readonly List DefaultIgnorePatterns = new List 58 | { 59 | @"/Editor/", 60 | @"/Editor Default Resources/", 61 | @"/Editor Resources/", 62 | @"ProjectSettings/", 63 | @"Packages/" 64 | }; 65 | 66 | // ReSharper disable once InconsistentNaming 67 | public const string PATTERNS_PREFS_KEY = "TextureHunterIgnoreSearchPatterns"; 68 | 69 | public List IgnoredPatterns { get; set; } 70 | } 71 | 72 | private enum OutputFilterType 73 | { 74 | Textures, 75 | Atlases 76 | } 77 | 78 | private class OutputSettings 79 | { 80 | public const int PageSize = 50; 81 | 82 | public string PathFilter { get; set; } 83 | public OutputFilterType TypeFilter { get; set; } 84 | 85 | public TexturesOutputSettings TexturesSettings { get; } = new TexturesOutputSettings(); 86 | public AtlasesOutputSettings AtlasesSettings { get; } = new AtlasesOutputSettings(); 87 | } 88 | 89 | private class AtlasesOutputSettings : IPaginationSettings 90 | { 91 | public int? PageToShow { get; set; } = 0; 92 | 93 | /// 94 | /// Sorting types. 95 | /// By warning level: 0: A-Z, 1: Z-A 96 | /// By path: 2: A-Z, 3: Z-A 97 | /// By size: 4: A-Z, 5: Z-A 98 | /// 99 | public int SortType { get; set; } 100 | 101 | public bool WarningsOnly { get; set; } 102 | } 103 | 104 | private class TexturesOutputSettings : IPaginationSettings 105 | { 106 | public int? PageToShow { get; set; } = 0; 107 | 108 | /// 109 | /// Sorting types. 110 | /// By warning level: 0: A-Z, 1: Z-A 111 | /// By path: 2: A-Z, 3: Z-A 112 | /// By size: 4: A-Z, 5: Z-A 113 | /// 114 | public int SortType { get; set; } 115 | 116 | public bool WarningsOnly { get; set; } 117 | } 118 | 119 | private interface IPaginationSettings 120 | { 121 | int? PageToShow { get; set; } 122 | } 123 | 124 | private abstract class ItemDataBase 125 | { 126 | public int WarningLevel { get; private set; } 127 | 128 | public void TrySetWarningLevel(int level) 129 | { 130 | if (level <= WarningLevel) return; 131 | WarningLevel = level; 132 | } 133 | 134 | public List CustomWarnings { get; private set; } 135 | 136 | public void AddCustomWarning(string warning) 137 | { 138 | CustomWarnings ??= new List(); 139 | CustomWarnings.Add(warning); 140 | } 141 | } 142 | 143 | private class AtlasData : ItemDataBase 144 | { 145 | public string Path { get; } 146 | public string Name => System.IO.Path.GetFileName(Path); 147 | public Type Type { get; } 148 | public string TypeName { get; } 149 | public string ReadableSize { get; } 150 | public List Packables { get; } 151 | public bool Foldout { get; set; } 152 | public Dictionary ImportSettings { get; } = 153 | new Dictionary(); 154 | public int SpritesCount { get; private set; } 155 | public SpriteAtlas Atlas { get; } 156 | 157 | public AtlasData( 158 | SpriteAtlas atlas, 159 | string path, 160 | Type type, 161 | string typeName, 162 | string readableSize, 163 | Dictionary> packablesDictionary) 164 | { 165 | Atlas = atlas; 166 | Path = path; 167 | Type = type; 168 | TypeName = typeName; 169 | ReadableSize = readableSize; 170 | Packables = new List(); 171 | 172 | foreach (var pair in packablesDictionary) 173 | { 174 | Packables.Add(new PackableData(pair.Key, pair.Value)); 175 | } 176 | } 177 | 178 | public void UpdateSpritesCount() 179 | { 180 | SpritesCount = Packables.Sum(packable => packable.Content.Count); 181 | } 182 | } 183 | 184 | private class AtlasPlatformImportSettings 185 | { 186 | public AtlasPlatformImportSettings( 187 | TextureImporterPlatformSettings settings, 188 | bool isDefault, 189 | TextureImporterFormat defaultFormat) 190 | { 191 | Settings = settings; 192 | 193 | FormatSet = Settings.format; 194 | 195 | CompressionQuality = Settings.compressionQuality; 196 | 197 | IsDefaultPlatform = isDefault; 198 | IsUsingDefaultSettings = !Settings.overridden; 199 | 200 | if (!isDefault && IsUsingDefaultSettings) 201 | { 202 | FormatActual = defaultFormat; 203 | 204 | if (FormatActual == TextureImporterFormat.Automatic) 205 | { 206 | Description = "Automatic"; 207 | } 208 | else 209 | { 210 | Description = "Automatic -> " + FormatActual; 211 | } 212 | } 213 | else 214 | { 215 | FormatActual = FormatSet; 216 | Description = FormatActual.ToString(); 217 | } 218 | 219 | Description += $"[Q{CompressionQuality}]"; 220 | } 221 | 222 | public bool IsDefaultPlatform { get; private set; } 223 | public TextureImporterPlatformSettings Settings { get; } 224 | private TextureImporterFormat FormatSet { get; } 225 | public TextureImporterFormat FormatActual { get; } 226 | private int CompressionQuality { get; } 227 | public string Description { get; } 228 | public bool IsUsingDefaultSettings { get; } 229 | } 230 | 231 | private class PackableData 232 | { 233 | public PackableData(string key, List content) 234 | { 235 | Key = key; 236 | Content = content; 237 | } 238 | 239 | public string Key { get; } 240 | public List Content { get; } 241 | } 242 | 243 | private class TextureData : ItemDataBase 244 | { 245 | private bool _importerLoaded; 246 | private bool _textureLoaded; 247 | 248 | private TextureImporter _importer; 249 | private Texture _texture; 250 | 251 | public TextureData( 252 | string path, 253 | Type type, 254 | string typeName, 255 | long bytesSize, 256 | string readableSize) 257 | { 258 | Path = path; 259 | Type = type; 260 | TypeName = typeName; 261 | BytesSize = bytesSize; 262 | ReadableSize = readableSize; 263 | 264 | InResources = Path.Contains("/Resources/"); 265 | 266 | IsAddressable = CommonUtilities.IsAssetAddressable(Path); 267 | } 268 | 269 | public string Path { get; } 270 | public string Name => System.IO.Path.GetFileName(Path); 271 | public Type Type { get; } 272 | public string TypeName { get; } 273 | public long BytesSize { get; } 274 | public string ReadableSize { get; } 275 | public bool Foldout { get; set; } 276 | 277 | public bool InResources { get; } 278 | public bool IsAddressable { get; } 279 | 280 | public Dictionary ImportSettings { get; } = 281 | new Dictionary(); 282 | 283 | public AtlasData Atlas { get; set; } 284 | 285 | public TextureImporter Importer 286 | { 287 | get 288 | { 289 | if (_importerLoaded) return _importer; 290 | _importerLoaded = true; 291 | _importer = AssetImporter.GetAtPath(Path) as TextureImporter; 292 | return _importer; 293 | } 294 | } 295 | 296 | private TextureInfo _info; 297 | 298 | public TextureInfo Info 299 | { 300 | get 301 | { 302 | if (_info != null) 303 | return _info; 304 | 305 | var texture = Texture; 306 | 307 | if (texture == null) 308 | return null; 309 | 310 | var width = texture.width; 311 | var height = texture.height; 312 | 313 | var isPot = CommonUtilities.IsPowerOfTwo(texture.width) && 314 | CommonUtilities.IsPowerOfTwo(texture.height); 315 | 316 | var isMultipleOfFour = texture.width % 4 == 0 && texture.height % 4 == 0; 317 | 318 | _info = new TextureInfo(width, height, isPot, isMultipleOfFour); 319 | 320 | _texture = null; 321 | 322 | return _info; 323 | } 324 | } 325 | 326 | private Texture Texture 327 | { 328 | get 329 | { 330 | if (_textureLoaded) return _texture; 331 | _textureLoaded = true; 332 | _texture = EditorGUIUtility.Load(Path) as Texture; 333 | return _texture; 334 | } 335 | } 336 | } 337 | 338 | private class TexturePlatformImportSettings 339 | { 340 | public TexturePlatformImportSettings(TextureImporter importer, 341 | string platform) 342 | { 343 | IsDefaultPlatform = platform == "Default"; 344 | Settings = IsDefaultPlatform ? importer.GetDefaultPlatformTextureSettings() 345 | : importer.GetPlatformTextureSettings(platform); 346 | 347 | FormatSet = Settings.format; 348 | 349 | CompressionQuality = Settings.compressionQuality; 350 | 351 | IsUsingDefaultSettings = FormatSet == TextureImporterFormat.Automatic; 352 | 353 | if (IsUsingDefaultSettings) 354 | { 355 | FormatActual = importer.GetAutomaticFormat(platform); 356 | 357 | if (FormatActual == TextureImporterFormat.Automatic) 358 | { 359 | Description = "Automatic"; 360 | } 361 | else 362 | { 363 | Description = "Automatic -> " + FormatActual; 364 | } 365 | } 366 | else 367 | { 368 | FormatActual = FormatSet; 369 | Description = FormatActual.ToString(); 370 | } 371 | 372 | Description += $"[Q{CompressionQuality}]"; 373 | 374 | ActualFormatAsLoweredString = FormatActual.ToString().ToLowerInvariant(); 375 | } 376 | 377 | public TextureImporterPlatformSettings Settings { get; } 378 | private TextureImporterFormat FormatSet { get; } 379 | public TextureImporterFormat FormatActual { get; } 380 | private int CompressionQuality { get; } 381 | public string Description { get; } 382 | public string ActualFormatAsLoweredString { get; } 383 | public bool IsUsingDefaultSettings { get; } 384 | public bool IsDefaultPlatform { get; } 385 | } 386 | 387 | private class TextureInfo 388 | { 389 | public TextureInfo(int width, int height, bool isPot, bool isMultipleOfFour) 390 | { 391 | Width = width; 392 | Height = height; 393 | IsPot = isPot; 394 | IsMultipleOfFour = isMultipleOfFour; 395 | } 396 | 397 | public int Width { get; } 398 | public int Height { get; } 399 | public bool IsPot { get; } 400 | public bool IsMultipleOfFour { get; } 401 | } 402 | 403 | [MenuItem("Tools/Texture Hunter")] 404 | public static void LaunchWindow() 405 | { 406 | GetWindow(); 407 | } 408 | 409 | private static void Clear() 410 | { 411 | EditorUtility.UnloadUnusedAssetsImmediate(); 412 | } 413 | 414 | private void OnDestroy() 415 | { 416 | Clear(); 417 | } 418 | 419 | private Result _result; 420 | private OutputSettings _outputSettings; 421 | private AnalysisSettings _analysisSettings; 422 | private SearchPatternsSettings _searchPatternsSettings; 423 | 424 | private bool _analysisSettingsFoldout; 425 | private bool _batchOperationsFoldout; 426 | private bool _searchPatternsSettingsFoldout; 427 | 428 | private bool _batchOperationsJustLog; 429 | 430 | private Vector2 _atlasesPagesScroll = Vector2.zero; 431 | private Vector2 _atlasesScroll = Vector2.zero; 432 | 433 | private Vector2 _texturesPagesScroll = Vector2.zero; 434 | private Vector2 _texturesScroll = Vector2.zero; 435 | 436 | // ReSharper disable once IdentifierTypo 437 | private const string WarningDuplicateInAddressables = "Possible duplicate in build: " + 438 | "this texture is addressable and in atlas"; 439 | private const string WarningDuplicateInResources = "Possible duplicate in build: " + 440 | "this texture is in Resources and in atlas"; 441 | private const string DuplicateInAtlas = "Duplicate in atlas: "; 442 | 443 | private const string AtlasContainsTextureThatExistsInAnotherAtlas 444 | = "Contains texture {0} that exists in another atlas"; 445 | 446 | private const string DimensionsFallbackIssue = "Texture is neither POT nor multiple of 4: " + 447 | "possible compression issue"; 448 | 449 | private bool _analysisOngoing; 450 | 451 | private IEnumerator PopulateAssetsList() 452 | { 453 | _analysisOngoing = true; 454 | 455 | _result = new Result(); 456 | _outputSettings ??= new OutputSettings(); 457 | 458 | if (_analysisSettings.GarbageCollectStep < 0) 459 | { 460 | _analysisSettings.GarbageCollectStep = AnalysisSettings.DefaultGCStep; 461 | } 462 | 463 | Clear(); 464 | Show(); 465 | 466 | EditorUtility.ClearProgressBar(); 467 | 468 | var assetPaths = AssetDatabase.GetAllAssetPaths(); 469 | 470 | var filteredOutput = new StringBuilder(); 471 | filteredOutput.AppendLine("Assets ignored by pattern:"); 472 | 473 | var count = 0; 474 | 475 | for (var assetIndex = 0; assetIndex < assetPaths.Length; assetIndex++) 476 | { 477 | if (_analysisSettings.GarbageCollectStep != 0 && assetIndex % _analysisSettings.GarbageCollectStep == 0) 478 | { 479 | GC.Collect(); 480 | yield return 0.05f; 481 | GC.Collect(); 482 | } 483 | 484 | var assetPath = assetPaths[assetIndex]; 485 | EditorUtility.DisplayProgressBar("Textures Hunter", "Scanning for atlases", 486 | (float)count / assetPaths.Length); 487 | 488 | var type = AssetDatabase.GetMainAssetTypeAtPath(assetPath); 489 | 490 | var validAssetType = type != null; 491 | 492 | if (!validAssetType) 493 | continue; 494 | 495 | if (type == typeof(SpriteAtlas)) 496 | { 497 | var validForOutput = IsValidForOutput(assetPath, 498 | _searchPatternsSettings.IgnoredPatterns); 499 | 500 | if (!validForOutput) 501 | { 502 | filteredOutput.AppendLine(assetPath); 503 | continue; 504 | } 505 | 506 | count++; 507 | 508 | _result.Atlases.Add(CreateAtlasData(assetPath)); 509 | 510 | if (_analysisSettings.DebugLimit > 0 && _result.Atlases.Count > _analysisSettings.DebugLimit) 511 | break; 512 | } 513 | } 514 | 515 | for (var assetIndex = 0; assetIndex < assetPaths.Length; assetIndex++) 516 | { 517 | if (_analysisSettings.GarbageCollectStep != 0 && assetIndex % _analysisSettings.GarbageCollectStep == 0) 518 | { 519 | GC.Collect(); 520 | yield return 0.05f; 521 | GC.Collect(); 522 | } 523 | 524 | var assetPath = assetPaths[assetIndex]; 525 | EditorUtility.DisplayProgressBar("Textures Hunter", "Scanning for textures", 526 | (float)count / assetPaths.Length); 527 | 528 | var type = AssetDatabase.GetMainAssetTypeAtPath(assetPath); 529 | 530 | var validAssetType = type != null; 531 | 532 | if (!validAssetType) 533 | continue; 534 | 535 | if (type != typeof(SpriteAtlas)) 536 | { 537 | count++; 538 | } 539 | 540 | if (type == typeof(Texture) || type == typeof(Texture2D)) 541 | { 542 | var textureData = CreateTextureData(assetPath); 543 | var atlasFound = TryProcessAsAtlasTexture(textureData); 544 | 545 | if (!atlasFound) 546 | { 547 | var validForOutput = IsValidForOutput(assetPath, 548 | _searchPatternsSettings.IgnoredPatterns); 549 | 550 | if (!validForOutput) 551 | { 552 | filteredOutput.AppendLine(assetPath); 553 | continue; 554 | } 555 | 556 | ProcessAsNonAtlasTexture(textureData); 557 | 558 | _result.Textures.Add(textureData); 559 | 560 | if (_analysisSettings.DebugLimit > 0 && _result.Textures.Count > _analysisSettings.DebugLimit) 561 | break; 562 | } 563 | } 564 | } 565 | 566 | GC.Collect(); 567 | 568 | if (_analysisSettings.GarbageCollectStep != 0) 569 | { 570 | yield return 0.1f; 571 | GC.Collect(); 572 | } 573 | 574 | PostProcessAtlases(); 575 | 576 | _result.OutputDescription = $"Atlases: {_result.Atlases.Count}. Textures: {_result.Textures.Count}"; 577 | 578 | SortAtlasesByWarnings(_result.Atlases, _outputSettings.AtlasesSettings); 579 | SortTexturesByWarnings(_result.Textures, _outputSettings.TexturesSettings); 580 | 581 | EditorUtility.ClearProgressBar(); 582 | 583 | Debug.Log(filteredOutput.ToString()); 584 | Debug.Log(_result.OutputDescription); 585 | filteredOutput.Clear(); 586 | 587 | _analysisOngoing = false; 588 | } 589 | 590 | private bool TryProcessAsAtlasTexture(TextureData textureData) 591 | { 592 | var atlasFound = false; 593 | AtlasData atlasCandidate = null; 594 | PackableData packableCandidate = null; 595 | 596 | foreach (var atlas in _result.Atlases) 597 | { 598 | foreach (var packable in atlas.Packables) 599 | { 600 | var isFolder = !Path.HasExtension(packable.Key); 601 | 602 | bool isAddedDirectly; 603 | bool isAddedViaFolder; 604 | 605 | if (isFolder) 606 | { 607 | isAddedDirectly = false; 608 | 609 | // Unity may store path with separators from another OS 610 | // so we need to check both cases and cannot just use Path.DirectorySeparatorChar 611 | 612 | // we have to ensure that there is a separator in the end of a packable folder 613 | // to filter folders which start with the same substring (like 'Asses/Buildings/' and 'Assets/BuildingsIcons/') 614 | 615 | var endsAsOnNix = packable.Key.EndsWith("/"); 616 | var endsAsOnWindows = packable.Key.EndsWith("\\"); 617 | 618 | if (endsAsOnNix || endsAsOnWindows) 619 | { 620 | isAddedViaFolder = textureData.Path.Contains(packable.Key); 621 | } 622 | else 623 | { 624 | isAddedViaFolder = textureData.Path.Contains(packable.Key + "/") || 625 | textureData.Path.Contains(packable.Key + "\\"); 626 | } 627 | } 628 | else 629 | { 630 | isAddedViaFolder = false; 631 | isAddedDirectly = textureData.Path == packable.Key; 632 | } 633 | 634 | if (isAddedDirectly || isAddedViaFolder) 635 | { 636 | atlasFound = true; 637 | 638 | if (atlasCandidate != null) 639 | { 640 | textureData.AddCustomWarning($"This texture's links to atlases ({atlas.Name}, {atlasCandidate.Name}) are ambiguous. " + 641 | "While Unity probably handles it in a deterministic way we still mark is as a warning because it may be error-prone for users."); 642 | textureData.TrySetWarningLevel(2); 643 | 644 | atlas.AddCustomWarning($"Atlas has ambiguous packables with atlas {atlasCandidate.Name} and its packable {packableCandidate.Key}"); 645 | atlas.TrySetWarningLevel(2); 646 | 647 | atlasCandidate.AddCustomWarning($"Atlas has ambiguous packables with atlas {atlas.Name} and its packable {packable.Key}"); 648 | atlasCandidate.TrySetWarningLevel(2); 649 | 650 | if (packableCandidate.Key.Length > packable.Key.Length) 651 | { 652 | // Unity usually prefers more concrete packables - so do us. 653 | // We assume that the larger the path the more concrete the packable. 654 | continue; 655 | } 656 | } 657 | 658 | atlasCandidate = atlas; 659 | packableCandidate = packable; 660 | } 661 | } 662 | } 663 | 664 | // ReSharper disable once ConditionIsAlwaysTrueOrFalse 665 | if (atlasCandidate != null && packableCandidate != null) 666 | { 667 | ApplyTextureToAtlas(textureData, atlasCandidate, packableCandidate); 668 | } 669 | 670 | return atlasFound; 671 | } 672 | 673 | private void ApplyTextureToAtlas(TextureData textureData, AtlasData atlas, PackableData packable) 674 | { 675 | if (textureData.IsAddressable) 676 | { 677 | textureData.AddCustomWarning(WarningDuplicateInAddressables); 678 | textureData.TrySetWarningLevel(1); 679 | atlas.TrySetWarningLevel(1); 680 | } 681 | 682 | if (textureData.Atlas != null) 683 | { 684 | textureData.AddCustomWarning(DuplicateInAtlas + textureData.Atlas.Name); 685 | textureData.TrySetWarningLevel(3); 686 | 687 | textureData.Atlas.TrySetWarningLevel(2); 688 | textureData.Atlas.AddCustomWarning( 689 | string.Format(AtlasContainsTextureThatExistsInAnotherAtlas, 690 | textureData.Name)); 691 | } 692 | 693 | textureData.Atlas = atlas; 694 | 695 | if (textureData.InResources) 696 | { 697 | textureData.AddCustomWarning(WarningDuplicateInResources); 698 | textureData.TrySetWarningLevel(2); 699 | } 700 | 701 | packable.Content.Add(textureData); 702 | } 703 | 704 | private void ProcessAsNonAtlasTexture(TextureData textureData) 705 | { 706 | var info = textureData.Info; 707 | 708 | if (!info.IsPot && !info.IsMultipleOfFour) 709 | { 710 | textureData.TrySetWarningLevel(1); 711 | textureData.AddCustomWarning(DimensionsFallbackIssue); 712 | } 713 | 714 | if (_analysisSettings.SizeHigher4KAreErrors && (info.Width > 4096 || info.Height > 4096)) 715 | { 716 | textureData.TrySetWarningLevel(2); 717 | textureData.AddCustomWarning("Size over 4096"); 718 | } 719 | 720 | var importer = textureData.Importer; 721 | 722 | if (importer == null) 723 | { 724 | textureData.TrySetWarningLevel(2); 725 | textureData.AddCustomWarning("Unable to load an importer"); 726 | return; 727 | } 728 | 729 | if (_analysisSettings.MipMapsAreErrors && importer.mipmapEnabled) 730 | { 731 | textureData.TrySetWarningLevel(2); 732 | textureData.AddCustomWarning("Mipmap is enabled. Is it intended?"); 733 | } 734 | 735 | if (_analysisSettings.ReadableAreErrors && importer.isReadable) 736 | { 737 | textureData.TrySetWarningLevel(2); 738 | textureData.AddCustomWarning("Texture is readable. Is it intended?"); 739 | } 740 | 741 | var iOSSettings = new TexturePlatformImportSettings(importer, "iOS"); 742 | var androidSettings = new TexturePlatformImportSettings(importer, "Android"); 743 | 744 | if (_analysisSettings.NoOverridenCompressionAsErrors) 745 | { 746 | if (iOSSettings.IsUsingDefaultSettings || androidSettings.IsUsingDefaultSettings) 747 | { 748 | textureData.TrySetWarningLevel(2); 749 | textureData.AddCustomWarning("Texture uses Automatic compression. Is it intended?"); 750 | } 751 | } 752 | 753 | textureData.ImportSettings["iOS"] = iOSSettings; 754 | textureData.ImportSettings["Android"] = androidSettings; 755 | 756 | textureData.ImportSettings["Default"] = new TexturePlatformImportSettings(importer, "Default"); 757 | 758 | foreach (var settings in textureData.ImportSettings) 759 | { 760 | if (settings.Value.ActualFormatAsLoweredString.Contains("crunch") && !info.IsMultipleOfFour) 761 | { 762 | textureData.TrySetWarningLevel(2); 763 | textureData.AddCustomWarning( 764 | $"{settings.Key}: only multiple of 4 textures can use crunch compression"); 765 | } 766 | 767 | if (settings.Value.ActualFormatAsLoweredString.Contains("pvrtc") && !info.IsPot) 768 | { 769 | textureData.TrySetWarningLevel(2); 770 | textureData.AddCustomWarning( 771 | $"{settings.Key}: only POT textures can use PVRTC format"); 772 | } 773 | 774 | if (!settings.Value.IsDefaultPlatform && !_analysisSettings.RecommendedFormats.Contains(settings.Value.FormatActual)) 775 | { 776 | textureData.TrySetWarningLevel(2); 777 | textureData.AddCustomWarning( 778 | $"{settings.Key}: does not use recommended compression"); 779 | } 780 | } 781 | } 782 | 783 | private void PostProcessAtlases() 784 | { 785 | foreach (var atlas in _result.Atlases) 786 | { 787 | atlas.UpdateSpritesCount(); 788 | 789 | if (atlas.Packables.Count == 0) 790 | { 791 | atlas.TrySetWarningLevel(2); 792 | atlas.AddCustomWarning("Packables list is empty"); 793 | } 794 | else if (atlas.SpritesCount == 0) 795 | { 796 | atlas.TrySetWarningLevel(1); 797 | atlas.AddCustomWarning("Unable to detect sprites. Might be an issue with packables or this tool could not find sprites within subfolders." + 798 | "We mark it as a warning because we suggest that this atlas settings might be confusing for users."); 799 | } 800 | } 801 | } 802 | 803 | private bool IsValidForOutput(string path, List ignoreInOutputPatterns) 804 | { 805 | return ignoreInOutputPatterns.All(pattern 806 | => string.IsNullOrEmpty(pattern) || !Regex.Match(path, pattern).Success); 807 | } 808 | 809 | private AtlasData CreateAtlasData(string path) 810 | { 811 | var fileInfo = new FileInfo(path); 812 | var bytesSize = fileInfo.Length; 813 | 814 | var type = AssetDatabase.GetMainAssetTypeAtPath(path); 815 | var typeName = CommonUtilities.GetReadableTypeName(type); 816 | 817 | var atlas = EditorGUIUtility.Load(path) as SpriteAtlas; 818 | 819 | var packables = atlas.GetPackables(); 820 | 821 | var defaultsAssets = packables.OfType(); 822 | var folders = defaultsAssets.Select(AssetDatabase.GetAssetPath).ToList(); 823 | 824 | var packablesDictionary = folders.ToDictionary(folder => folder, _ => new List()); 825 | 826 | var directTextures = packables.OfType(); 827 | 828 | foreach (var directTexture in directTextures) 829 | { 830 | var textureName = AssetDatabase.GetAssetPath(directTexture); 831 | if (!packablesDictionary.ContainsKey(textureName)) 832 | { 833 | packablesDictionary.Add(textureName, new List()); 834 | } 835 | else 836 | { 837 | Debug.LogWarning($"Texture name [{textureName}]" + 838 | $" is presented in the atlas [{path}] twice"); 839 | } 840 | } 841 | 842 | var atlasData = new AtlasData(atlas, path, type, typeName, 843 | CommonUtilities.GetReadableSize(bytesSize), packablesDictionary); 844 | 845 | ProcessSpriteAtlasTexture(atlasData, atlas); 846 | 847 | return atlasData; 848 | } 849 | 850 | private void ProcessSpriteAtlasTexture(AtlasData atlasData, SpriteAtlas atlas) 851 | { 852 | var iOSAutomatic = false; 853 | var androidAutomatic = false; 854 | 855 | var textureSettings = atlas.GetTextureSettings(); 856 | 857 | 858 | var defaultPlatformSettings = atlas.GetPlatformSettings("DefaultTexturePlatform"); 859 | 860 | if (defaultPlatformSettings == null) 861 | { 862 | atlasData.TrySetWarningLevel(2); 863 | atlasData.AddCustomWarning("Unable to retrieve default importer settings"); 864 | return; 865 | } 866 | 867 | var defaultSettings = new AtlasPlatformImportSettings(defaultPlatformSettings, true, defaultPlatformSettings.format); 868 | atlasData.ImportSettings["Default"] = defaultSettings; 869 | 870 | var androidPlatformSettings = atlas.GetPlatformSettings("Android"); 871 | 872 | if (androidPlatformSettings != null) 873 | { 874 | var androidSettings = 875 | new AtlasPlatformImportSettings(androidPlatformSettings, false, defaultPlatformSettings.format); 876 | androidAutomatic = androidSettings.IsUsingDefaultSettings; 877 | atlasData.ImportSettings["Android"] = androidSettings; 878 | 879 | if (!_analysisSettings.RecommendedFormats.Contains(androidSettings.FormatActual)) 880 | { 881 | atlasData.TrySetWarningLevel(2); 882 | atlasData.AddCustomWarning( 883 | $"Does not use recommended compression"); 884 | } 885 | } 886 | 887 | var iOSPlatformSettings = atlas.GetPlatformSettings("iPhone"); 888 | 889 | if (iOSPlatformSettings != null) 890 | { 891 | var iOSSettings = 892 | new AtlasPlatformImportSettings(iOSPlatformSettings, false, defaultPlatformSettings.format); 893 | iOSAutomatic = iOSSettings.IsUsingDefaultSettings; 894 | atlasData.ImportSettings["iOS"] = iOSSettings; 895 | 896 | if (!_analysisSettings.RecommendedFormats.Contains(iOSSettings.FormatActual)) 897 | { 898 | atlasData.TrySetWarningLevel(2); 899 | atlasData.AddCustomWarning( 900 | $"Does not use recommended compression"); 901 | } 902 | } 903 | 904 | if (_analysisSettings.MipMapsAreErrors && textureSettings.generateMipMaps) 905 | { 906 | atlasData.TrySetWarningLevel(2); 907 | atlasData.AddCustomWarning("Mipmap is enabled. Is it intended?"); 908 | } 909 | 910 | if (_analysisSettings.NoOverridenCompressionAsErrors) 911 | { 912 | if (iOSAutomatic || androidAutomatic) 913 | { 914 | atlasData.TrySetWarningLevel(2); 915 | atlasData.AddCustomWarning("Atlas uses Automatic compression. Is it intended?"); 916 | } 917 | } 918 | } 919 | 920 | private TextureData CreateTextureData(string path) 921 | { 922 | var fileInfo = new FileInfo(path); 923 | var bytesSize = fileInfo.Length; 924 | 925 | var type = AssetDatabase.GetMainAssetTypeAtPath(path); 926 | var typeName = CommonUtilities.GetReadableTypeName(type); 927 | 928 | return new TextureData(path, type, typeName, bytesSize, CommonUtilities.GetReadableSize(bytesSize)); 929 | } 930 | 931 | private void SetAtlasesQuality(string platform, bool performChanges = true, int crunchedQuality = 30, int astcQuality = 50) 932 | { 933 | if (_result == null) 934 | return; 935 | 936 | var counter = 0; 937 | 938 | foreach (var atlas in _result.Atlases) 939 | { 940 | foreach (var setting in atlas.ImportSettings) 941 | { 942 | if (!setting.Value.IsDefaultPlatform && !setting.Value.IsUsingDefaultSettings && setting.Key == platform) 943 | { 944 | if (setting.Value.FormatActual == TextureImporterFormat.ETC2_RGBA8Crunched) 945 | { 946 | if (setting.Value.Settings.compressionQuality != crunchedQuality) 947 | { 948 | Debug.LogWarning($"Changing: {atlas.Name} / {setting.Key} quality to {crunchedQuality}"); 949 | 950 | if (performChanges) 951 | { 952 | setting.Value.Settings.compressionQuality = crunchedQuality; 953 | atlas.Atlas.SetPlatformSettings(setting.Value.Settings); 954 | } 955 | 956 | counter++; 957 | } 958 | } 959 | else if (CommonUtilities.IsAnyAstc(setting.Value.FormatActual)) 960 | { 961 | var isDirty = false; 962 | 963 | var redundantLevel = 964 | setting.Value.FormatActual == TextureImporterFormat.ASTC_5x5 || setting.Value.FormatActual == TextureImporterFormat.ASTC_4x4; 965 | 966 | if (redundantLevel) 967 | { 968 | Debug.LogWarning( 969 | $"Changing: {atlas.Name} / {setting.Key} format to {TextureImporterFormat.ASTC_6x6}"); 970 | 971 | if (performChanges) 972 | setting.Value.Settings.format = TextureImporterFormat.ASTC_6x6; 973 | isDirty = true; 974 | } 975 | 976 | if (setting.Value.Settings.compressionQuality != astcQuality) 977 | { 978 | Debug.LogWarning( 979 | $"Changing: {atlas.Name} / {setting.Key} format to quality {astcQuality}"); 980 | 981 | if (performChanges) 982 | setting.Value.Settings.compressionQuality = astcQuality; 983 | isDirty = true; 984 | } 985 | 986 | if (isDirty) 987 | { 988 | if (performChanges) 989 | atlas.Atlas.SetPlatformSettings(setting.Value.Settings); 990 | counter++; 991 | } 992 | } 993 | } 994 | } 995 | } 996 | 997 | Debug.LogWarning($"Changed {counter} atlases"); 998 | 999 | AssetDatabase.SaveAssets(); 1000 | } 1001 | 1002 | private IEnumerator SetTexturesQuality(string platform, bool performChanges = true, int crunchedQuality = 30, int astcQuality = 50) 1003 | { 1004 | if (_result == null) 1005 | yield break; 1006 | 1007 | _analysisOngoing = true; 1008 | 1009 | var changeCounter = 0; 1010 | 1011 | foreach (var texture in _result.Textures) 1012 | { 1013 | var prevCounter = changeCounter; 1014 | 1015 | SetTextureQuality(platform, ref changeCounter, texture, performChanges, crunchedQuality, astcQuality); 1016 | 1017 | if (prevCounter != changeCounter && changeCounter % 100 == 0) 1018 | { 1019 | GC.Collect(); 1020 | Debug.Log($"GC call. Changed {changeCounter} textures"); 1021 | yield return 0.05f; 1022 | GC.Collect(); 1023 | } 1024 | } 1025 | 1026 | Debug.LogWarning($"Changed {changeCounter} textures"); 1027 | 1028 | _analysisOngoing = false; 1029 | 1030 | AssetDatabase.SaveAssets(); 1031 | } 1032 | 1033 | private void SetTextureQuality(string platform, ref int counter, TextureData texture, bool performChanges = true, 1034 | int crunchedQuality = 30, int astcQuality = 50) 1035 | { 1036 | foreach (var setting in texture.ImportSettings) 1037 | { 1038 | if (!setting.Value.IsDefaultPlatform && !setting.Value.IsUsingDefaultSettings && setting.Key == platform) 1039 | { 1040 | if (setting.Value.FormatActual == TextureImporterFormat.ETC2_RGBA8Crunched) 1041 | { 1042 | if (setting.Value.Settings.compressionQuality != crunchedQuality) 1043 | { 1044 | var importer = texture.Importer; 1045 | 1046 | if (importer != null) 1047 | { 1048 | Debug.LogWarning( 1049 | $"Changing: {texture.Name} / {setting.Key} quality to {crunchedQuality}"); 1050 | 1051 | if (performChanges) 1052 | { 1053 | setting.Value.Settings.compressionQuality = crunchedQuality; 1054 | 1055 | importer.SetPlatformTextureSettings(setting.Value.Settings); 1056 | importer.SaveAndReimport(); 1057 | } 1058 | 1059 | counter++; 1060 | } 1061 | } 1062 | } 1063 | else if (CommonUtilities.IsAnyAstc(setting.Value.FormatActual)) 1064 | { 1065 | var importer = texture.Importer; 1066 | 1067 | if (importer != null) 1068 | { 1069 | var isDirty = false; 1070 | 1071 | var redundantLevel = 1072 | setting.Value.FormatActual == TextureImporterFormat.ASTC_5x5 || setting.Value.FormatActual == TextureImporterFormat.ASTC_4x4; 1073 | 1074 | if (redundantLevel) 1075 | { 1076 | Debug.LogWarning( 1077 | $"Changing: {texture.Name} / {setting.Key} format to {TextureImporterFormat.ASTC_6x6}"); 1078 | if (performChanges) 1079 | setting.Value.Settings.format = TextureImporterFormat.ASTC_6x6; 1080 | isDirty = true; 1081 | } 1082 | 1083 | if (setting.Value.Settings.compressionQuality != astcQuality) 1084 | { 1085 | Debug.LogWarning( 1086 | $"Changing: {texture.Name} / {setting.Key} format to quality {astcQuality}"); 1087 | if (performChanges) 1088 | setting.Value.Settings.compressionQuality = astcQuality; 1089 | isDirty = true; 1090 | } 1091 | 1092 | if (isDirty) 1093 | { 1094 | if (performChanges) 1095 | { 1096 | importer.SetPlatformTextureSettings(setting.Value.Settings); 1097 | importer.SaveAndReimport(); 1098 | } 1099 | 1100 | counter++; 1101 | } 1102 | } 1103 | } 1104 | } 1105 | } 1106 | } 1107 | 1108 | private IEnumerator FixTexturesAutomaticCompression(string platform, TextureImporterFormat format, 1109 | int quality, bool performChanges = true) 1110 | { 1111 | if (_result == null) 1112 | yield break; 1113 | 1114 | _analysisOngoing = true; 1115 | 1116 | var changeCounter = 0; 1117 | 1118 | foreach (var texture in _result.Textures) 1119 | { 1120 | if (texture.WarningLevel < 2) 1121 | continue; 1122 | 1123 | if (!texture.ImportSettings.ContainsKey(platform)) 1124 | continue; 1125 | 1126 | var settings = texture.ImportSettings[platform]; 1127 | 1128 | if (!settings.IsUsingDefaultSettings) 1129 | continue; 1130 | 1131 | settings.Settings.format = format; 1132 | settings.Settings.compressionQuality = quality; 1133 | 1134 | if (performChanges) 1135 | { 1136 | texture.Importer.SetPlatformTextureSettings(settings.Settings); 1137 | texture.Importer.SaveAndReimport(); 1138 | } 1139 | 1140 | changeCounter++; 1141 | 1142 | if (changeCounter % 100 == 0) 1143 | { 1144 | GC.Collect(); 1145 | Debug.Log($"GC call. Changed {changeCounter} textures"); 1146 | yield return 0.05f; 1147 | GC.Collect(); 1148 | } 1149 | } 1150 | 1151 | Debug.LogWarning($"Changed {changeCounter} textures"); 1152 | 1153 | _analysisOngoing = false; 1154 | 1155 | AssetDatabase.SaveAssets(); 1156 | } 1157 | 1158 | private void OnGUI() 1159 | { 1160 | EditorGUILayout.BeginHorizontal(); 1161 | 1162 | GUILayout.FlexibleSpace(); 1163 | 1164 | var prevColor = GUI.color; 1165 | GUI.color = Color.green; 1166 | 1167 | if (!_analysisOngoing) 1168 | { 1169 | var postfix = _result != null ? " (Overrides last results)" : string.Empty; 1170 | if (GUILayout.Button($"Run Analysis{postfix}", GUILayout.Width(300f))) 1171 | { 1172 | PocketEditorCoroutine.Start(PopulateAssetsList(), this); 1173 | } 1174 | } 1175 | else 1176 | { 1177 | GUILayout.Label("Analysis ongoing..."); 1178 | } 1179 | 1180 | GUI.color = prevColor; 1181 | 1182 | GUILayout.FlexibleSpace(); 1183 | 1184 | EditorGUILayout.EndHorizontal(); 1185 | 1186 | OnSearchPatternsSettingsGUI(); 1187 | OnAnalysisSettingsGUI(); 1188 | 1189 | GUIUtilities.HorizontalLine(); 1190 | 1191 | if (_result == null || _analysisOngoing) 1192 | { 1193 | return; 1194 | } 1195 | 1196 | EditorGUILayout.BeginHorizontal(); 1197 | EditorGUILayout.LabelField(_result.OutputDescription); 1198 | 1199 | EditorGUILayout.EndHorizontal(); 1200 | 1201 | GUIUtilities.HorizontalLine(); 1202 | 1203 | _batchOperationsFoldout = EditorGUILayout.Foldout(_batchOperationsFoldout, "Batch Operations"); 1204 | 1205 | if (_batchOperationsFoldout) 1206 | { 1207 | _batchOperationsJustLog = EditorGUILayout.Toggle("Just log", _batchOperationsJustLog); 1208 | 1209 | EditorGUILayout.BeginHorizontal(); 1210 | 1211 | if (GUILayout.Button("[Android] Atlases: Set ETC2 Crunched quality to 30; min ASTC to 6x6 and quality to 50")) 1212 | { 1213 | SetAtlasesQuality("Android", !_batchOperationsJustLog); 1214 | } 1215 | 1216 | if (GUILayout.Button("[Android] Textures: Set ETC2 Crunched quality to 30; min ASTC to 6x6 and quality to 50")) 1217 | { 1218 | PocketEditorCoroutine.Start(SetTexturesQuality("Android", !_batchOperationsJustLog), this); 1219 | } 1220 | 1221 | EditorGUILayout.EndHorizontal(); 1222 | 1223 | EditorGUILayout.BeginHorizontal(); 1224 | 1225 | if (GUILayout.Button("[iOS] Atlases: Set ETC2 Crunched quality to 30; min ASTC to 6x6 and quality to 50")) 1226 | { 1227 | SetAtlasesQuality("iOS", !_batchOperationsJustLog); 1228 | } 1229 | 1230 | if (GUILayout.Button("[iOS] Textures: Set ETC2 Crunched quality to 30; min ASTC to 6x6 and quality to 50")) 1231 | { 1232 | PocketEditorCoroutine.Start(SetTexturesQuality("iOS", !_batchOperationsJustLog), this); 1233 | } 1234 | 1235 | EditorGUILayout.EndHorizontal(); 1236 | 1237 | EditorGUILayout.BeginHorizontal(); 1238 | 1239 | if (GUILayout.Button("[Android] Textures: Override all non yet overriden textures to ASTC 8x8")) 1240 | { 1241 | PocketEditorCoroutine.Start(FixTexturesAutomaticCompression("Android", TextureImporterFormat.ASTC_8x8, 50, !_batchOperationsJustLog), this); 1242 | } 1243 | 1244 | if (GUILayout.Button("[iOS] Textures: Override all non yet overriden textures to ASTC 8x8")) 1245 | { 1246 | PocketEditorCoroutine.Start(FixTexturesAutomaticCompression("iOS", TextureImporterFormat.ASTC_8x8, 50, !_batchOperationsJustLog), this); 1247 | } 1248 | 1249 | EditorGUILayout.EndHorizontal(); 1250 | } 1251 | 1252 | GUIUtilities.HorizontalLine(); 1253 | 1254 | EditorGUILayout.BeginHorizontal(); 1255 | 1256 | prevColor = GUI.color; 1257 | 1258 | var prevAlignment = GUI.skin.button.alignment; 1259 | GUI.skin.button.alignment = TextAnchor.MiddleLeft; 1260 | 1261 | GUI.color = _outputSettings.TypeFilter == OutputFilterType.Textures ? Color.yellow : Color.white; 1262 | 1263 | if (GUILayout.Button($"[{_result.Textures.Count}] Textures (non-atlas)", GUILayout.Width(200f))) 1264 | { 1265 | _outputSettings.TypeFilter = OutputFilterType.Textures; 1266 | } 1267 | 1268 | GUI.color = _outputSettings.TypeFilter == OutputFilterType.Atlases ? Color.yellow : Color.white; 1269 | 1270 | if (GUILayout.Button($"[{_result.Atlases.Count}] Atlases", GUILayout.Width(200f))) 1271 | { 1272 | _outputSettings.TypeFilter = OutputFilterType.Atlases; 1273 | } 1274 | 1275 | GUI.skin.button.alignment = prevAlignment; 1276 | GUI.color = prevColor; 1277 | 1278 | EditorGUILayout.EndHorizontal(); 1279 | 1280 | GUIUtilities.HorizontalLine(); 1281 | 1282 | EditorGUILayout.BeginHorizontal(); 1283 | 1284 | var textFieldStyle = EditorStyles.textField; 1285 | var prevTextFieldAlignment = textFieldStyle.alignment; 1286 | textFieldStyle.alignment = TextAnchor.MiddleCenter; 1287 | 1288 | _outputSettings.PathFilter = EditorGUILayout.TextField("Path Contains:", 1289 | _outputSettings.PathFilter, GUILayout.Width(400f)); 1290 | 1291 | textFieldStyle.alignment = prevTextFieldAlignment; 1292 | 1293 | EditorGUILayout.EndHorizontal(); 1294 | 1295 | 1296 | 1297 | GUIUtilities.HorizontalLine(); 1298 | 1299 | switch (_outputSettings.TypeFilter) 1300 | { 1301 | case OutputFilterType.Atlases: 1302 | OnDrawAtlases(_result.Atlases, _outputSettings.PathFilter, _outputSettings.AtlasesSettings); 1303 | break; 1304 | case OutputFilterType.Textures: 1305 | OnDrawTextures(_result.Textures, _outputSettings.PathFilter, _outputSettings.TexturesSettings); 1306 | break; 1307 | } 1308 | } 1309 | 1310 | private void OnDrawAtlases(List atlases, string pathFilter, AtlasesOutputSettings settings) 1311 | { 1312 | if (_result.Atlases.Count == 0) 1313 | { 1314 | EditorGUILayout.LabelField("No atlases found"); 1315 | return; 1316 | } 1317 | 1318 | EditorGUILayout.BeginHorizontal(); 1319 | 1320 | var prevColor = GUI.color; 1321 | 1322 | var sortType = settings.SortType; 1323 | 1324 | GUI.color = sortType == 0 || sortType == 1 ? Color.yellow : Color.white; 1325 | var orderType = sortType == 1 ? "Z-A" : "A-Z"; 1326 | if (GUILayout.Button("Sort by warnings " + orderType, GUILayout.Width(150f))) 1327 | { 1328 | SortAtlasesByWarnings(atlases, settings); 1329 | } 1330 | 1331 | GUI.color = sortType == 2 || sortType == 3 ? Color.yellow : Color.white; 1332 | orderType = sortType == 3 ? "Z-A" : "A-Z"; 1333 | if (GUILayout.Button("Sort by path " + orderType, GUILayout.Width(150f))) 1334 | { 1335 | SortAtlasesByPath(atlases, settings); 1336 | } 1337 | 1338 | GUI.color = sortType == 4 || sortType == 5 ? Color.yellow : Color.white; 1339 | orderType = sortType == 5 ? "Z-A" : "A-Z"; 1340 | if (GUILayout.Button("Sort by sprites count " + orderType, GUILayout.Width(200f))) 1341 | { 1342 | SortAtlasesBySpritesCount(atlases, settings); 1343 | } 1344 | 1345 | GUI.color = settings.WarningsOnly ? Color.yellow : Color.white; 1346 | if (GUILayout.Button("Warnings Level 2+ Only", GUILayout.Width(250f))) 1347 | { 1348 | settings.WarningsOnly = !settings.WarningsOnly; 1349 | } 1350 | 1351 | GUI.color = prevColor; 1352 | 1353 | EditorGUILayout.EndHorizontal(); 1354 | 1355 | var filteredAssets = atlases; 1356 | 1357 | if (settings.WarningsOnly) 1358 | { 1359 | filteredAssets = filteredAssets.Where(x => x.WarningLevel > 1).ToList(); 1360 | } 1361 | 1362 | if (!string.IsNullOrEmpty(pathFilter)) 1363 | { 1364 | filteredAssets = filteredAssets.Where(x => x.Path.Contains(pathFilter)).ToList(); 1365 | } 1366 | 1367 | DrawPagesWidget(filteredAssets.Count, settings, ref _atlasesPagesScroll); 1368 | 1369 | GUIUtilities.HorizontalLine(); 1370 | 1371 | _atlasesScroll = GUILayout.BeginScrollView(_atlasesScroll); 1372 | 1373 | EditorGUILayout.BeginVertical(); 1374 | 1375 | for (var i = 0; i < filteredAssets.Count; i++) 1376 | { 1377 | if (settings.PageToShow.HasValue) 1378 | { 1379 | var page = settings.PageToShow.Value; 1380 | if (i < page * OutputSettings.PageSize || i >= (page + 1) * OutputSettings.PageSize) 1381 | { 1382 | continue; 1383 | } 1384 | } 1385 | 1386 | var asset = filteredAssets[i]; 1387 | EditorGUILayout.BeginHorizontal(); 1388 | 1389 | if (GUILayout.Button(asset.Foldout ? ">Minimize" : ">Expand", GUILayout.Width(70))) 1390 | { 1391 | asset.Foldout = !asset.Foldout; 1392 | } 1393 | 1394 | prevColor = GUI.color; 1395 | 1396 | if (asset.WarningLevel > 2) 1397 | GUI.color = Color.red; 1398 | else if (asset.WarningLevel == 2) 1399 | GUI.color = Color.yellow; 1400 | else if (asset.WarningLevel == 1) 1401 | GUI.color = new Color(0.44f, 0.79f, 1f); 1402 | 1403 | EditorGUILayout.LabelField(i.ToString(), GUILayout.Width(40f)); 1404 | 1405 | EditorGUILayout.LabelField(asset.TypeName, GUILayout.Width(150f)); 1406 | 1407 | EditorGUILayout.LabelField($"Warning: {asset.WarningLevel}", GUILayout.Width(70f)); 1408 | 1409 | GUI.color = prevColor; 1410 | 1411 | var guiContent = EditorGUIUtility.ObjectContent(null, asset.Type); 1412 | guiContent.text = Path.GetFileName(asset.Path); 1413 | 1414 | var alignment = GUI.skin.button.alignment; 1415 | GUI.skin.button.alignment = TextAnchor.MiddleLeft; 1416 | 1417 | if (GUILayout.Button(guiContent, GUILayout.Width(300f), GUILayout.Height(18f))) 1418 | { 1419 | Selection.objects = new[] { AssetDatabase.LoadMainAssetAtPath(asset.Path) }; 1420 | } 1421 | 1422 | GUI.skin.button.alignment = alignment; 1423 | 1424 | EditorGUILayout.LabelField("Sprites: " + asset.SpritesCount, GUILayout.Width(100f)); 1425 | 1426 | foreach (var importSettings in asset.ImportSettings) 1427 | { 1428 | EditorGUILayout.LabelField(importSettings.Key + " : " + importSettings.Value.Description, GUILayout.Width(235)); 1429 | } 1430 | 1431 | GUI.color = prevColor; 1432 | 1433 | EditorGUILayout.EndHorizontal(); 1434 | 1435 | if (asset.Foldout) 1436 | { 1437 | GUILayout.Space(3); 1438 | EditorGUILayout.LabelField($"Atlas Path: {asset.Path}. Self file size: {asset.ReadableSize}"); 1439 | 1440 | var textureIndex = 0; 1441 | 1442 | foreach (var packable in asset.Packables) 1443 | { 1444 | var isFolder = !Path.HasExtension(packable.Key); 1445 | EditorGUILayout.LabelField($"Packable {(isFolder ? "(folder)" : string.Empty)}: {packable.Key}"); 1446 | 1447 | foreach (var textureData in packable.Content) 1448 | { 1449 | DrawTexture(textureIndex, textureData); 1450 | textureIndex++; 1451 | } 1452 | } 1453 | 1454 | GUIUtilities.HorizontalLine(); 1455 | 1456 | if (asset.CustomWarnings != null) 1457 | { 1458 | EditorGUILayout.LabelField($"Warnings [{asset.CustomWarnings.Count}]:"); 1459 | foreach (var customWarning in asset.CustomWarnings) 1460 | { 1461 | EditorGUILayout.LabelField(customWarning); 1462 | } 1463 | 1464 | GUIUtilities.HorizontalLine(); 1465 | } 1466 | } 1467 | } 1468 | 1469 | GUILayout.FlexibleSpace(); 1470 | 1471 | EditorGUILayout.EndVertical(); 1472 | GUILayout.EndScrollView(); 1473 | } 1474 | 1475 | private void OnDrawTextures(List textures, string pathFilter, TexturesOutputSettings settings) 1476 | { 1477 | if (_result.Textures.Count == 0) 1478 | { 1479 | EditorGUILayout.LabelField("No textures found"); 1480 | return; 1481 | } 1482 | 1483 | EditorGUILayout.BeginHorizontal(); 1484 | 1485 | var prevColor = GUI.color; 1486 | 1487 | var sortType = settings.SortType; 1488 | 1489 | GUI.color = sortType == 0 || sortType == 1 ? Color.yellow : Color.white; 1490 | var orderType = sortType == 1 ? "Z-A" : "A-Z"; 1491 | if (GUILayout.Button("Sort by warnings " + orderType, GUILayout.Width(150f))) 1492 | { 1493 | SortTexturesByWarnings(textures, settings); 1494 | } 1495 | 1496 | GUI.color = sortType == 2 || sortType == 3 ? Color.yellow : Color.white; 1497 | orderType = sortType == 3 ? "Z-A" : "A-Z"; 1498 | if (GUILayout.Button("Sort by path " + orderType, GUILayout.Width(150f))) 1499 | { 1500 | SortTexturesByPath(textures, settings); 1501 | } 1502 | 1503 | GUI.color = sortType == 4 || sortType == 5 ? Color.yellow : Color.white; 1504 | orderType = sortType == 5 ? "Z-A" : "A-Z"; 1505 | if (GUILayout.Button("Sort by size " + orderType, GUILayout.Width(150f))) 1506 | { 1507 | SortTexturesBySize(textures, settings); 1508 | } 1509 | 1510 | GUI.color = settings.WarningsOnly ? Color.yellow : Color.white; 1511 | if (GUILayout.Button("Warnings Level 2+ Only", GUILayout.Width(250f))) 1512 | { 1513 | settings.WarningsOnly = !settings.WarningsOnly; 1514 | } 1515 | 1516 | GUI.color = prevColor; 1517 | 1518 | EditorGUILayout.EndHorizontal(); 1519 | 1520 | var filteredAssets = textures; 1521 | 1522 | if (settings.WarningsOnly) 1523 | { 1524 | filteredAssets = filteredAssets.Where(x => x.WarningLevel > 1).ToList(); 1525 | } 1526 | 1527 | if (!string.IsNullOrEmpty(pathFilter)) 1528 | { 1529 | filteredAssets = filteredAssets.Where(x => x.Path.Contains(pathFilter)).ToList(); 1530 | } 1531 | 1532 | DrawPagesWidget(filteredAssets.Count, settings, ref _texturesPagesScroll); 1533 | 1534 | GUIUtilities.HorizontalLine(); 1535 | 1536 | _texturesScroll = GUILayout.BeginScrollView(_texturesScroll); 1537 | 1538 | EditorGUILayout.BeginVertical(); 1539 | 1540 | for (var i = 0; i < filteredAssets.Count; i++) 1541 | { 1542 | if (settings.PageToShow.HasValue) 1543 | { 1544 | var page = settings.PageToShow.Value; 1545 | if (i < page * OutputSettings.PageSize || i >= (page + 1) * OutputSettings.PageSize) 1546 | { 1547 | continue; 1548 | } 1549 | } 1550 | 1551 | var asset = filteredAssets[i]; 1552 | DrawTexture(i, asset); 1553 | } 1554 | 1555 | GUILayout.FlexibleSpace(); 1556 | 1557 | EditorGUILayout.EndVertical(); 1558 | GUILayout.EndScrollView(); 1559 | } 1560 | 1561 | private void DrawTexture(int i, TextureData asset) 1562 | { 1563 | EditorGUILayout.BeginHorizontal(); 1564 | 1565 | if (GUILayout.Button(asset.Foldout ? "Minimize" : "Expand", GUILayout.Width(70))) 1566 | { 1567 | asset.Foldout = !asset.Foldout; 1568 | } 1569 | 1570 | var prevColor = GUI.color; 1571 | 1572 | if (asset.WarningLevel > 2) 1573 | GUI.color = Color.red; 1574 | else if (asset.WarningLevel == 2) 1575 | GUI.color = Color.yellow; 1576 | else if (asset.WarningLevel == 1) 1577 | GUI.color = new Color(0.44f, 0.79f, 1f); 1578 | 1579 | EditorGUILayout.LabelField(i.ToString(), GUILayout.Width(40f)); 1580 | 1581 | EditorGUILayout.LabelField(asset.TypeName, GUILayout.Width(70f)); 1582 | 1583 | EditorGUILayout.LabelField($"Warning: {asset.WarningLevel}", GUILayout.Width(70f)); 1584 | 1585 | var guiContent = EditorGUIUtility.ObjectContent(null, asset.Type); 1586 | guiContent.text = Path.GetFileName(asset.Path); 1587 | 1588 | var alignment = GUI.skin.button.alignment; 1589 | GUI.skin.button.alignment = TextAnchor.MiddleLeft; 1590 | 1591 | if (GUILayout.Button(guiContent, GUILayout.Width(300f), GUILayout.Height(18f))) 1592 | { 1593 | Selection.objects = new[] { AssetDatabase.LoadMainAssetAtPath(asset.Path) }; 1594 | } 1595 | 1596 | GUI.skin.button.alignment = alignment; 1597 | 1598 | EditorGUILayout.LabelField(asset.ReadableSize, GUILayout.Width(70f)); 1599 | 1600 | GUI.color = prevColor; 1601 | 1602 | if (asset.Info != null) 1603 | { 1604 | EditorGUILayout.LabelField($"{asset.Info.Width}x{asset.Info.Height}", GUILayout.Width(80)); 1605 | 1606 | var isPot = asset.Info.IsPot; 1607 | 1608 | prevColor = GUI.color; 1609 | GUI.color = isPot ? Color.green : Color.gray; 1610 | 1611 | EditorGUILayout.LabelField(isPot ? "POT" : "Non-POT", GUILayout.Width(60)); 1612 | 1613 | var isMultipleOfFour = asset.Info.IsMultipleOfFour; 1614 | 1615 | GUI.color = isMultipleOfFour ? Color.green : Color.gray; 1616 | EditorGUILayout.LabelField(isMultipleOfFour ? "Multiple of 4" : "Non Multiple of 4", 1617 | GUILayout.Width(120)); 1618 | 1619 | GUI.color = prevColor; 1620 | } 1621 | else 1622 | { 1623 | prevColor = GUI.color; 1624 | GUI.color = Color.red; 1625 | EditorGUILayout.LabelField("Texture is null", GUILayout.Width(140)); 1626 | GUI.color = prevColor; 1627 | } 1628 | 1629 | foreach (var settings in asset.ImportSettings) 1630 | { 1631 | EditorGUILayout.LabelField(settings.Key + " : " + settings.Value.Description, GUILayout.Width(235)); 1632 | } 1633 | 1634 | GUI.color = prevColor; 1635 | 1636 | EditorGUILayout.EndHorizontal(); 1637 | 1638 | if (asset.Foldout) 1639 | { 1640 | GUILayout.Space(3); 1641 | EditorGUILayout.LabelField($"Path: {asset.Path}"); 1642 | GUIUtilities.HorizontalLine(); 1643 | 1644 | if (asset.CustomWarnings != null) 1645 | { 1646 | EditorGUILayout.LabelField($"Warnings [{asset.CustomWarnings.Count}]:"); 1647 | foreach (var customWarning in asset.CustomWarnings) 1648 | { 1649 | EditorGUILayout.LabelField(customWarning); 1650 | } 1651 | 1652 | GUIUtilities.HorizontalLine(); 1653 | } 1654 | } 1655 | } 1656 | 1657 | private void DrawPagesWidget(int assetsCount, IPaginationSettings settings, ref Vector2 scroll) 1658 | { 1659 | scroll = EditorGUILayout.BeginScrollView(scroll); 1660 | 1661 | EditorGUILayout.BeginHorizontal(); 1662 | 1663 | var prevColor = GUI.color; 1664 | GUI.color = !settings.PageToShow.HasValue ? Color.yellow : Color.white; 1665 | 1666 | if (GUILayout.Button("All", GUILayout.Width(30f))) 1667 | { 1668 | settings.PageToShow = null; 1669 | } 1670 | 1671 | GUI.color = prevColor; 1672 | 1673 | var totalCount = assetsCount; 1674 | var pagesCount = totalCount / OutputSettings.PageSize + (totalCount % OutputSettings.PageSize > 0 ? 1 : 0); 1675 | 1676 | for (var i = 0; i < pagesCount; i++) 1677 | { 1678 | prevColor = GUI.color; 1679 | GUI.color = settings.PageToShow == i ? Color.yellow : Color.white; 1680 | 1681 | if (GUILayout.Button((i + 1).ToString(), GUILayout.Width(30f))) 1682 | { 1683 | settings.PageToShow = i; 1684 | } 1685 | 1686 | GUI.color = prevColor; 1687 | } 1688 | 1689 | if (settings.PageToShow.HasValue && settings.PageToShow > pagesCount - 1) 1690 | { 1691 | settings.PageToShow = pagesCount - 1; 1692 | } 1693 | 1694 | if (settings.PageToShow.HasValue && pagesCount == 0) 1695 | { 1696 | settings.PageToShow = null; 1697 | } 1698 | 1699 | EditorGUILayout.EndHorizontal(); 1700 | EditorGUILayout.EndScrollView(); 1701 | } 1702 | 1703 | private void OnAnalysisSettingsGUI() 1704 | { 1705 | EnsureAnalysisSettingsLoaded(); 1706 | 1707 | _analysisSettingsFoldout = EditorGUILayout.Foldout(_analysisSettingsFoldout, 1708 | "Analysis Settings."); 1709 | 1710 | if (!_analysisSettingsFoldout) 1711 | return; 1712 | 1713 | GUILayout.BeginHorizontal(); 1714 | 1715 | if (GUILayout.Button($"No platform overriden compression as error: {_analysisSettings.NoOverridenCompressionAsErrors}")) 1716 | { 1717 | _analysisSettings.NoOverridenCompressionAsErrors = !_analysisSettings.NoOverridenCompressionAsErrors; 1718 | } 1719 | 1720 | if (GUILayout.Button($"MipmapEnabled as error: {_analysisSettings.MipMapsAreErrors}")) 1721 | { 1722 | _analysisSettings.MipMapsAreErrors = !_analysisSettings.MipMapsAreErrors; 1723 | } 1724 | 1725 | if (GUILayout.Button($"(Non Atlas) IsReadable as error: {_analysisSettings.ReadableAreErrors}")) 1726 | { 1727 | _analysisSettings.ReadableAreErrors = !_analysisSettings.ReadableAreErrors; 1728 | } 1729 | 1730 | if (GUILayout.Button($"(Non Atlas) Height/Width > 4k as error: {_analysisSettings.SizeHigher4KAreErrors}")) 1731 | { 1732 | _analysisSettings.SizeHigher4KAreErrors = !_analysisSettings.SizeHigher4KAreErrors; 1733 | } 1734 | 1735 | GUILayout.EndHorizontal(); 1736 | 1737 | GUILayout.Label( 1738 | "*If you face OOM during analysis then try to lower GC parameter below"); 1739 | _analysisSettings.GarbageCollectStep = EditorGUILayout.IntField("GC once in (iterations):", _analysisSettings.GarbageCollectStep); 1740 | 1741 | GUILayout.Label( 1742 | "*Below is a debug option to limit number of assets in the analysis"); 1743 | _analysisSettings.DebugLimit = EditorGUILayout.IntField("Assets Debug Limit:", _analysisSettings.DebugLimit); 1744 | 1745 | GUILayout.Label("Recommended Formats"); 1746 | 1747 | var count = _analysisSettings.RecommendedFormats.Count; 1748 | 1749 | GUILayout.BeginHorizontal(); 1750 | 1751 | if (count > 0) 1752 | { 1753 | if (GUILayout.Button("Remove")) 1754 | { 1755 | count--; 1756 | } 1757 | } 1758 | 1759 | if (GUILayout.Button("Add")) 1760 | { 1761 | count++; 1762 | } 1763 | 1764 | GUILayout.FlexibleSpace(); 1765 | 1766 | GUILayout.EndHorizontal(); 1767 | 1768 | if (count != _analysisSettings.RecommendedFormats.Count) 1769 | { 1770 | var newList = new List(count); 1771 | 1772 | for (var i = 0; i < count; i++) 1773 | { 1774 | var importerFormat = i < _analysisSettings.RecommendedFormats.Count ? _analysisSettings.RecommendedFormats[i] 1775 | : TextureImporterFormat.ASTC_6x6; 1776 | newList.Add(importerFormat); 1777 | } 1778 | 1779 | _analysisSettings.RecommendedFormats = newList; 1780 | } 1781 | 1782 | var formats = _analysisSettings.RecommendedFormats; 1783 | 1784 | for (var i = 0; i < formats.Count; i++) 1785 | { 1786 | formats[i] = (TextureImporterFormat)EditorGUILayout.EnumPopup($"[{i}] Format: {formats[i]}", formats[i]); 1787 | } 1788 | } 1789 | 1790 | private void OnSearchPatternsSettingsGUI() 1791 | { 1792 | EnsureSearchPatternsLoaded(); 1793 | 1794 | _searchPatternsSettingsFoldout = EditorGUILayout.Foldout(_searchPatternsSettingsFoldout, 1795 | $"Search Patterns Settings. Patterns Ignored in Output: {_searchPatternsSettings.IgnoredPatterns.Count}."); 1796 | 1797 | if (!_searchPatternsSettingsFoldout) 1798 | return; 1799 | 1800 | EditorGUILayout.LabelField("Any changes here will be applied in the next 'Run Analysis' call", GUILayout.Width(350f)); 1801 | 1802 | var isPatternsListDirty = false; 1803 | 1804 | EditorGUILayout.BeginHorizontal(); 1805 | EditorGUILayout.LabelField("Format: RegExp patterns"); 1806 | if (GUILayout.Button("Set Default", GUILayout.Width(300f))) 1807 | { 1808 | _searchPatternsSettings.IgnoredPatterns = _searchPatternsSettings.DefaultIgnorePatterns.ToList(); 1809 | isPatternsListDirty = true; 1810 | } 1811 | 1812 | if (GUILayout.Button("Save to Clipboard")) 1813 | { 1814 | var contents = _searchPatternsSettings.IgnoredPatterns.Aggregate("Patterns:", 1815 | (current, t) => current + "\n" + t); 1816 | 1817 | EditorGUIUtility.systemCopyBuffer = contents; 1818 | } 1819 | 1820 | EditorGUILayout.EndHorizontal(); 1821 | 1822 | var newCount = Mathf.Max(0, EditorGUILayout.IntField("Count:", _searchPatternsSettings.IgnoredPatterns.Count)); 1823 | 1824 | if (newCount != _searchPatternsSettings.IgnoredPatterns.Count) 1825 | { 1826 | isPatternsListDirty = true; 1827 | } 1828 | 1829 | while (newCount < _searchPatternsSettings.IgnoredPatterns.Count) 1830 | { 1831 | _searchPatternsSettings.IgnoredPatterns.RemoveAt(_searchPatternsSettings.IgnoredPatterns.Count - 1); 1832 | } 1833 | 1834 | if (newCount > _searchPatternsSettings.IgnoredPatterns.Count) 1835 | { 1836 | for (var i = _searchPatternsSettings.IgnoredPatterns.Count; i < newCount; i++) 1837 | { 1838 | _searchPatternsSettings.IgnoredPatterns.Add(EditorPrefs.GetString($"{SearchPatternsSettings.PATTERNS_PREFS_KEY}_{i}")); 1839 | } 1840 | } 1841 | 1842 | for (var i = 0; i < _searchPatternsSettings.IgnoredPatterns.Count; i++) 1843 | { 1844 | var newValue = EditorGUILayout.TextField(_searchPatternsSettings.IgnoredPatterns[i]); 1845 | if (_searchPatternsSettings.IgnoredPatterns[i] != newValue) 1846 | { 1847 | isPatternsListDirty = true; 1848 | _searchPatternsSettings.IgnoredPatterns[i] = newValue; 1849 | } 1850 | } 1851 | 1852 | if (isPatternsListDirty) 1853 | { 1854 | SaveSearchPatterns(); 1855 | } 1856 | } 1857 | 1858 | private void EnsureAnalysisSettingsLoaded() 1859 | { 1860 | // ReSharper disable once ConvertIfStatementToNullCoalescingAssignment 1861 | if (_analysisSettings == null) 1862 | { 1863 | _analysisSettings = new AnalysisSettings(); 1864 | } 1865 | } 1866 | 1867 | private void EnsureSearchPatternsLoaded() 1868 | { 1869 | // ReSharper disable once ConvertIfStatementToNullCoalescingAssignment 1870 | if (_searchPatternsSettings == null) 1871 | { 1872 | _searchPatternsSettings = new SearchPatternsSettings(); 1873 | } 1874 | 1875 | if (_searchPatternsSettings.IgnoredPatterns != null) 1876 | { 1877 | return; 1878 | } 1879 | 1880 | var count = EditorPrefs.GetInt(SearchPatternsSettings.PATTERNS_PREFS_KEY, -1); 1881 | 1882 | if (count == -1) 1883 | { 1884 | _searchPatternsSettings.IgnoredPatterns = _searchPatternsSettings.DefaultIgnorePatterns.ToList(); 1885 | } 1886 | else 1887 | { 1888 | _searchPatternsSettings.IgnoredPatterns = new List(); 1889 | 1890 | for (var i = 0; i < count; i++) 1891 | { 1892 | _searchPatternsSettings.IgnoredPatterns.Add(EditorPrefs.GetString($"{SearchPatternsSettings.PATTERNS_PREFS_KEY}_{i}")); 1893 | } 1894 | } 1895 | } 1896 | 1897 | private void SaveSearchPatterns() 1898 | { 1899 | EditorPrefs.SetInt(SearchPatternsSettings.PATTERNS_PREFS_KEY, _searchPatternsSettings.IgnoredPatterns.Count); 1900 | 1901 | for (var i = 0; i < _searchPatternsSettings.IgnoredPatterns.Count; i++) 1902 | { 1903 | EditorPrefs.SetString($"{SearchPatternsSettings.PATTERNS_PREFS_KEY}_{i}", _searchPatternsSettings.IgnoredPatterns[i]); 1904 | } 1905 | } 1906 | 1907 | private static void SortAtlasesByWarnings(List atlases, AtlasesOutputSettings settings) 1908 | { 1909 | if (settings.SortType == 0) 1910 | { 1911 | settings.SortType = 1; 1912 | atlases?.Sort((a, b) => 1913 | b.WarningLevel.CompareTo(a.WarningLevel)); 1914 | } 1915 | else 1916 | { 1917 | settings.SortType = 0; 1918 | atlases?.Sort((a, b) => 1919 | a.WarningLevel.CompareTo(b.WarningLevel)); 1920 | } 1921 | } 1922 | 1923 | private static void SortAtlasesByPath(List atlases, AtlasesOutputSettings settings) 1924 | { 1925 | if (settings.SortType == 2) 1926 | { 1927 | settings.SortType = 3; 1928 | atlases?.Sort((a, b) => 1929 | string.Compare(b.Path, a.Path, StringComparison.Ordinal)); 1930 | } 1931 | else 1932 | { 1933 | settings.SortType = 2; 1934 | atlases?.Sort((a, b) => 1935 | string.Compare(a.Path, b.Path, StringComparison.Ordinal)); 1936 | } 1937 | } 1938 | 1939 | private static void SortAtlasesBySpritesCount(List atlases, AtlasesOutputSettings settings) 1940 | { 1941 | if (settings.SortType == 4) 1942 | { 1943 | settings.SortType = 5; 1944 | atlases?.Sort((b, a) => a.SpritesCount.CompareTo(b.SpritesCount)); 1945 | } 1946 | else 1947 | { 1948 | settings.SortType = 4; 1949 | atlases?.Sort((a, b) => a.SpritesCount.CompareTo(b.SpritesCount)); 1950 | } 1951 | } 1952 | 1953 | private static void SortTexturesByWarnings(List textures, TexturesOutputSettings settings) 1954 | { 1955 | if (settings.SortType == 0) 1956 | { 1957 | settings.SortType = 1; 1958 | textures?.Sort((a, b) => 1959 | b.WarningLevel.CompareTo(a.WarningLevel)); 1960 | } 1961 | else 1962 | { 1963 | settings.SortType = 0; 1964 | textures?.Sort((a, b) => 1965 | a.WarningLevel.CompareTo(b.WarningLevel)); 1966 | } 1967 | } 1968 | 1969 | private static void SortTexturesByPath(List textures, TexturesOutputSettings settings) 1970 | { 1971 | if (settings.SortType == 2) 1972 | { 1973 | settings.SortType = 3; 1974 | textures?.Sort((a, b) => 1975 | string.Compare(b.Path, a.Path, StringComparison.Ordinal)); 1976 | } 1977 | else 1978 | { 1979 | settings.SortType = 2; 1980 | textures?.Sort((a, b) => 1981 | string.Compare(a.Path, b.Path, StringComparison.Ordinal)); 1982 | } 1983 | } 1984 | 1985 | private static void SortTexturesBySize(List textures, TexturesOutputSettings settings) 1986 | { 1987 | if (settings.SortType == 4) 1988 | { 1989 | settings.SortType = 5; 1990 | textures?.Sort((b, a) => a.BytesSize.CompareTo(b.BytesSize)); 1991 | } 1992 | else 1993 | { 1994 | settings.SortType = 4; 1995 | textures?.Sort((a, b) => a.BytesSize.CompareTo(b.BytesSize)); 1996 | } 1997 | } 1998 | } 1999 | 2000 | public static class GUIUtilities 2001 | { 2002 | private static void HorizontalLine( 2003 | int marginTop, 2004 | int marginBottom, 2005 | int height, 2006 | Color color 2007 | ) 2008 | { 2009 | EditorGUILayout.BeginHorizontal(); 2010 | var rect = EditorGUILayout.GetControlRect( 2011 | false, 2012 | height, 2013 | new GUIStyle { margin = new RectOffset(0, 0, marginTop, marginBottom) } 2014 | ); 2015 | 2016 | EditorGUI.DrawRect(rect, color); 2017 | EditorGUILayout.EndHorizontal(); 2018 | } 2019 | 2020 | public static void HorizontalLine( 2021 | int marginTop = 5, 2022 | int marginBottom = 5, 2023 | int height = 2 2024 | ) 2025 | { 2026 | HorizontalLine(marginTop, marginBottom, height, new Color(0.5f, 0.5f, 0.5f, 1)); 2027 | } 2028 | } 2029 | 2030 | public static class CommonUtilities 2031 | { 2032 | public static bool IsPowerOfTwo(int x) 2033 | { 2034 | return x != 0 && (x & (x - 1)) == 0; 2035 | } 2036 | 2037 | public static bool IsAnyAstc(TextureImporterFormat format) 2038 | { 2039 | return format == TextureImporterFormat.ASTC_4x4 || format == TextureImporterFormat.ASTC_5x5 || format == TextureImporterFormat.ASTC_6x6 || format == TextureImporterFormat.ASTC_8x8 || format == TextureImporterFormat.ASTC_10x10 || format == TextureImporterFormat.ASTC_12x12; 2040 | } 2041 | 2042 | public static string GetReadableTypeName(Type type) 2043 | { 2044 | string typeName; 2045 | 2046 | if (type != null) 2047 | { 2048 | typeName = type.ToString(); 2049 | typeName = typeName.Replace("UnityEngine.", string.Empty); 2050 | typeName = typeName.Replace("UnityEditor.", string.Empty); 2051 | } 2052 | else 2053 | { 2054 | typeName = "Unknown Type"; 2055 | } 2056 | 2057 | return typeName; 2058 | } 2059 | 2060 | public static string GetReadableSize(long bytesSize) 2061 | { 2062 | string[] sizes = { "B", "KB", "MB", "GB", "TB" }; 2063 | double len = bytesSize; 2064 | var order = 0; 2065 | while (len >= 1024 && order < sizes.Length - 1) 2066 | { 2067 | order++; 2068 | len = len / 1024; 2069 | } 2070 | 2071 | return $"{len:0.##} {sizes[order]}"; 2072 | } 2073 | 2074 | public static bool IsAssetAddressable(string assetPath) 2075 | { 2076 | #if HUNT_ADDRESSABLES 2077 | var settings = AddressableAssetSettingsDefaultObject.Settings; 2078 | var entry = settings.FindAssetEntry(AssetDatabase.AssetPathToGUID(assetPath)); 2079 | return entry != null; 2080 | #else 2081 | return false; 2082 | #endif 2083 | } 2084 | } 2085 | 2086 | internal class PocketEditorCoroutine 2087 | { 2088 | private readonly bool _hasOwner; 2089 | private readonly WeakReference _ownerReference; 2090 | private IEnumerator _routine; 2091 | private double? _lastTimeWaitStarted; 2092 | 2093 | public static PocketEditorCoroutine Start(IEnumerator routine, EditorWindow owner = null) 2094 | { 2095 | return new PocketEditorCoroutine(routine, owner); 2096 | } 2097 | 2098 | private PocketEditorCoroutine(IEnumerator routine, EditorWindow owner = null) 2099 | { 2100 | _routine = routine ?? throw new ArgumentNullException(nameof(routine)); 2101 | EditorApplication.update += OnUpdate; 2102 | if (owner == null) return; 2103 | _ownerReference = new WeakReference(owner); 2104 | _hasOwner = true; 2105 | } 2106 | 2107 | public void Stop() 2108 | { 2109 | EditorApplication.update -= OnUpdate; 2110 | _routine = null; 2111 | } 2112 | 2113 | private void OnUpdate() 2114 | { 2115 | if (_hasOwner && (_ownerReference == null || (_ownerReference != null && !_ownerReference.IsAlive))) 2116 | { 2117 | Stop(); 2118 | return; 2119 | } 2120 | 2121 | var result = MoveNext(_routine); 2122 | if (!result.HasValue || result.Value) return; 2123 | Stop(); 2124 | } 2125 | 2126 | private bool? MoveNext(IEnumerator enumerator) 2127 | { 2128 | if (enumerator.Current is float current) 2129 | { 2130 | _lastTimeWaitStarted ??= EditorApplication.timeSinceStartup; 2131 | if (!(_lastTimeWaitStarted.Value + current <= EditorApplication.timeSinceStartup)) 2132 | return null; 2133 | _lastTimeWaitStarted = null; 2134 | } 2135 | return enumerator.MoveNext(); 2136 | } 2137 | } 2138 | } -------------------------------------------------------------------------------- /Packages/TextureHunter/Editor/TextureHunter.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: fa8fcaecb147f4249a05eb4165b42764 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Packages/TextureHunter/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Alexey Perov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Packages/TextureHunter/LICENSE.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3cddc2982489c034787517f8be606b57 3 | DefaultImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Packages/TextureHunter/README.md: -------------------------------------------------------------------------------- 1 | 2 | ## Installation 3 | Install via git url by adding this entry in your **manifest.json** 4 | 5 | `"unity-dependencies-hunter": "https://github.com/AlexeyPerov/Unity-Texture-Hunter.git#upm"` -------------------------------------------------------------------------------- /Packages/TextureHunter/README.md.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: df50c01820a0fb54592a8f18870429d0 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Packages/TextureHunter/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "texture-hunter", 3 | "version": "0.0.1", 4 | "displayName": "Texture Hunter", 5 | "description": "Unity project texture analysis tool.", 6 | "unity": "2019.3", 7 | "keywords": [ 8 | "references", 9 | "tool" 10 | ], 11 | "author": { 12 | "name": "Alexey Perov", 13 | "url": "https://github.com/AlexeyPerov/Unity-Texture-Hunter" 14 | } 15 | } -------------------------------------------------------------------------------- /Packages/TextureHunter/package.json.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9f4595f99d95359468bf8d3fbaf7f71e 3 | PackageManifestImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Packages/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "com.unity.2d.animation": "5.0.9", 4 | "com.unity.2d.pixel-perfect": "4.0.1", 5 | "com.unity.2d.psdimporter": "4.1.2", 6 | "com.unity.2d.sprite": "1.0.0", 7 | "com.unity.2d.spriteshape": "5.1.6", 8 | "com.unity.2d.tilemap": "1.0.0", 9 | "com.unity.collab-proxy": "1.15.4", 10 | "com.unity.ide.rider": "2.0.7", 11 | "com.unity.ide.visualstudio": "2.0.12", 12 | "com.unity.ide.vscode": "1.2.4", 13 | "com.unity.test-framework": "1.1.29", 14 | "com.unity.textmeshpro": "3.0.6", 15 | "com.unity.timeline": "1.4.8", 16 | "com.unity.ugui": "1.0.0", 17 | "com.unity.modules.ai": "1.0.0", 18 | "com.unity.modules.androidjni": "1.0.0", 19 | "com.unity.modules.animation": "1.0.0", 20 | "com.unity.modules.assetbundle": "1.0.0", 21 | "com.unity.modules.audio": "1.0.0", 22 | "com.unity.modules.cloth": "1.0.0", 23 | "com.unity.modules.director": "1.0.0", 24 | "com.unity.modules.imageconversion": "1.0.0", 25 | "com.unity.modules.imgui": "1.0.0", 26 | "com.unity.modules.jsonserialize": "1.0.0", 27 | "com.unity.modules.particlesystem": "1.0.0", 28 | "com.unity.modules.physics": "1.0.0", 29 | "com.unity.modules.physics2d": "1.0.0", 30 | "com.unity.modules.screencapture": "1.0.0", 31 | "com.unity.modules.terrain": "1.0.0", 32 | "com.unity.modules.terrainphysics": "1.0.0", 33 | "com.unity.modules.tilemap": "1.0.0", 34 | "com.unity.modules.ui": "1.0.0", 35 | "com.unity.modules.uielements": "1.0.0", 36 | "com.unity.modules.umbra": "1.0.0", 37 | "com.unity.modules.unityanalytics": "1.0.0", 38 | "com.unity.modules.unitywebrequest": "1.0.0", 39 | "com.unity.modules.unitywebrequestassetbundle": "1.0.0", 40 | "com.unity.modules.unitywebrequestaudio": "1.0.0", 41 | "com.unity.modules.unitywebrequesttexture": "1.0.0", 42 | "com.unity.modules.unitywebrequestwww": "1.0.0", 43 | "com.unity.modules.vehicles": "1.0.0", 44 | "com.unity.modules.video": "1.0.0", 45 | "com.unity.modules.vr": "1.0.0", 46 | "com.unity.modules.wind": "1.0.0", 47 | "com.unity.modules.xr": "1.0.0" 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Packages/packages-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "com.unity.2d.animation": { 4 | "version": "5.0.9", 5 | "depth": 0, 6 | "source": "registry", 7 | "dependencies": { 8 | "com.unity.2d.common": "4.0.3", 9 | "com.unity.mathematics": "1.1.0", 10 | "com.unity.2d.sprite": "1.0.0", 11 | "com.unity.modules.animation": "1.0.0", 12 | "com.unity.modules.uielements": "1.0.0" 13 | }, 14 | "url": "https://packages.unity.com" 15 | }, 16 | "com.unity.2d.common": { 17 | "version": "4.0.3", 18 | "depth": 1, 19 | "source": "registry", 20 | "dependencies": { 21 | "com.unity.2d.sprite": "1.0.0", 22 | "com.unity.modules.uielements": "1.0.0" 23 | }, 24 | "url": "https://packages.unity.com" 25 | }, 26 | "com.unity.2d.path": { 27 | "version": "4.0.2", 28 | "depth": 1, 29 | "source": "registry", 30 | "dependencies": {}, 31 | "url": "https://packages.unity.com" 32 | }, 33 | "com.unity.2d.pixel-perfect": { 34 | "version": "4.0.1", 35 | "depth": 0, 36 | "source": "registry", 37 | "dependencies": {}, 38 | "url": "https://packages.unity.com" 39 | }, 40 | "com.unity.2d.psdimporter": { 41 | "version": "4.1.2", 42 | "depth": 0, 43 | "source": "registry", 44 | "dependencies": { 45 | "com.unity.2d.common": "4.0.3", 46 | "com.unity.2d.animation": "5.0.9", 47 | "com.unity.2d.sprite": "1.0.0" 48 | }, 49 | "url": "https://packages.unity.com" 50 | }, 51 | "com.unity.2d.sprite": { 52 | "version": "1.0.0", 53 | "depth": 0, 54 | "source": "builtin", 55 | "dependencies": {} 56 | }, 57 | "com.unity.2d.spriteshape": { 58 | "version": "5.1.6", 59 | "depth": 0, 60 | "source": "registry", 61 | "dependencies": { 62 | "com.unity.mathematics": "1.1.0", 63 | "com.unity.2d.common": "4.0.3", 64 | "com.unity.2d.path": "4.0.2", 65 | "com.unity.modules.physics2d": "1.0.0" 66 | }, 67 | "url": "https://packages.unity.com" 68 | }, 69 | "com.unity.2d.tilemap": { 70 | "version": "1.0.0", 71 | "depth": 0, 72 | "source": "builtin", 73 | "dependencies": {} 74 | }, 75 | "com.unity.collab-proxy": { 76 | "version": "1.15.4", 77 | "depth": 0, 78 | "source": "registry", 79 | "dependencies": { 80 | "com.unity.nuget.newtonsoft-json": "2.0.0", 81 | "com.unity.services.core": "1.0.1" 82 | }, 83 | "url": "https://packages.unity.com" 84 | }, 85 | "com.unity.ext.nunit": { 86 | "version": "1.0.6", 87 | "depth": 1, 88 | "source": "registry", 89 | "dependencies": {}, 90 | "url": "https://packages.unity.com" 91 | }, 92 | "com.unity.ide.rider": { 93 | "version": "2.0.7", 94 | "depth": 0, 95 | "source": "registry", 96 | "dependencies": { 97 | "com.unity.test-framework": "1.1.1" 98 | }, 99 | "url": "https://packages.unity.com" 100 | }, 101 | "com.unity.ide.visualstudio": { 102 | "version": "2.0.12", 103 | "depth": 0, 104 | "source": "registry", 105 | "dependencies": { 106 | "com.unity.test-framework": "1.1.9" 107 | }, 108 | "url": "https://packages.unity.com" 109 | }, 110 | "com.unity.ide.vscode": { 111 | "version": "1.2.4", 112 | "depth": 0, 113 | "source": "registry", 114 | "dependencies": {}, 115 | "url": "https://packages.unity.com" 116 | }, 117 | "com.unity.mathematics": { 118 | "version": "1.1.0", 119 | "depth": 1, 120 | "source": "registry", 121 | "dependencies": {}, 122 | "url": "https://packages.unity.com" 123 | }, 124 | "com.unity.nuget.newtonsoft-json": { 125 | "version": "2.0.0", 126 | "depth": 1, 127 | "source": "registry", 128 | "dependencies": {}, 129 | "url": "https://packages.unity.com" 130 | }, 131 | "com.unity.services.core": { 132 | "version": "1.0.1", 133 | "depth": 1, 134 | "source": "registry", 135 | "dependencies": { 136 | "com.unity.modules.unitywebrequest": "1.0.0" 137 | }, 138 | "url": "https://packages.unity.com" 139 | }, 140 | "com.unity.test-framework": { 141 | "version": "1.1.29", 142 | "depth": 0, 143 | "source": "registry", 144 | "dependencies": { 145 | "com.unity.ext.nunit": "1.0.6", 146 | "com.unity.modules.imgui": "1.0.0", 147 | "com.unity.modules.jsonserialize": "1.0.0" 148 | }, 149 | "url": "https://packages.unity.com" 150 | }, 151 | "com.unity.textmeshpro": { 152 | "version": "3.0.6", 153 | "depth": 0, 154 | "source": "registry", 155 | "dependencies": { 156 | "com.unity.ugui": "1.0.0" 157 | }, 158 | "url": "https://packages.unity.com" 159 | }, 160 | "com.unity.timeline": { 161 | "version": "1.4.8", 162 | "depth": 0, 163 | "source": "registry", 164 | "dependencies": { 165 | "com.unity.modules.director": "1.0.0", 166 | "com.unity.modules.animation": "1.0.0", 167 | "com.unity.modules.audio": "1.0.0", 168 | "com.unity.modules.particlesystem": "1.0.0" 169 | }, 170 | "url": "https://packages.unity.com" 171 | }, 172 | "com.unity.ugui": { 173 | "version": "1.0.0", 174 | "depth": 0, 175 | "source": "builtin", 176 | "dependencies": { 177 | "com.unity.modules.ui": "1.0.0", 178 | "com.unity.modules.imgui": "1.0.0" 179 | } 180 | }, 181 | "texture-hunter": { 182 | "version": "file:TextureHunter", 183 | "depth": 0, 184 | "source": "embedded", 185 | "dependencies": {} 186 | }, 187 | "com.unity.modules.ai": { 188 | "version": "1.0.0", 189 | "depth": 0, 190 | "source": "builtin", 191 | "dependencies": {} 192 | }, 193 | "com.unity.modules.androidjni": { 194 | "version": "1.0.0", 195 | "depth": 0, 196 | "source": "builtin", 197 | "dependencies": {} 198 | }, 199 | "com.unity.modules.animation": { 200 | "version": "1.0.0", 201 | "depth": 0, 202 | "source": "builtin", 203 | "dependencies": {} 204 | }, 205 | "com.unity.modules.assetbundle": { 206 | "version": "1.0.0", 207 | "depth": 0, 208 | "source": "builtin", 209 | "dependencies": {} 210 | }, 211 | "com.unity.modules.audio": { 212 | "version": "1.0.0", 213 | "depth": 0, 214 | "source": "builtin", 215 | "dependencies": {} 216 | }, 217 | "com.unity.modules.cloth": { 218 | "version": "1.0.0", 219 | "depth": 0, 220 | "source": "builtin", 221 | "dependencies": { 222 | "com.unity.modules.physics": "1.0.0" 223 | } 224 | }, 225 | "com.unity.modules.director": { 226 | "version": "1.0.0", 227 | "depth": 0, 228 | "source": "builtin", 229 | "dependencies": { 230 | "com.unity.modules.audio": "1.0.0", 231 | "com.unity.modules.animation": "1.0.0" 232 | } 233 | }, 234 | "com.unity.modules.imageconversion": { 235 | "version": "1.0.0", 236 | "depth": 0, 237 | "source": "builtin", 238 | "dependencies": {} 239 | }, 240 | "com.unity.modules.imgui": { 241 | "version": "1.0.0", 242 | "depth": 0, 243 | "source": "builtin", 244 | "dependencies": {} 245 | }, 246 | "com.unity.modules.jsonserialize": { 247 | "version": "1.0.0", 248 | "depth": 0, 249 | "source": "builtin", 250 | "dependencies": {} 251 | }, 252 | "com.unity.modules.particlesystem": { 253 | "version": "1.0.0", 254 | "depth": 0, 255 | "source": "builtin", 256 | "dependencies": {} 257 | }, 258 | "com.unity.modules.physics": { 259 | "version": "1.0.0", 260 | "depth": 0, 261 | "source": "builtin", 262 | "dependencies": {} 263 | }, 264 | "com.unity.modules.physics2d": { 265 | "version": "1.0.0", 266 | "depth": 0, 267 | "source": "builtin", 268 | "dependencies": {} 269 | }, 270 | "com.unity.modules.screencapture": { 271 | "version": "1.0.0", 272 | "depth": 0, 273 | "source": "builtin", 274 | "dependencies": { 275 | "com.unity.modules.imageconversion": "1.0.0" 276 | } 277 | }, 278 | "com.unity.modules.subsystems": { 279 | "version": "1.0.0", 280 | "depth": 1, 281 | "source": "builtin", 282 | "dependencies": { 283 | "com.unity.modules.jsonserialize": "1.0.0" 284 | } 285 | }, 286 | "com.unity.modules.terrain": { 287 | "version": "1.0.0", 288 | "depth": 0, 289 | "source": "builtin", 290 | "dependencies": {} 291 | }, 292 | "com.unity.modules.terrainphysics": { 293 | "version": "1.0.0", 294 | "depth": 0, 295 | "source": "builtin", 296 | "dependencies": { 297 | "com.unity.modules.physics": "1.0.0", 298 | "com.unity.modules.terrain": "1.0.0" 299 | } 300 | }, 301 | "com.unity.modules.tilemap": { 302 | "version": "1.0.0", 303 | "depth": 0, 304 | "source": "builtin", 305 | "dependencies": { 306 | "com.unity.modules.physics2d": "1.0.0" 307 | } 308 | }, 309 | "com.unity.modules.ui": { 310 | "version": "1.0.0", 311 | "depth": 0, 312 | "source": "builtin", 313 | "dependencies": {} 314 | }, 315 | "com.unity.modules.uielements": { 316 | "version": "1.0.0", 317 | "depth": 0, 318 | "source": "builtin", 319 | "dependencies": { 320 | "com.unity.modules.ui": "1.0.0", 321 | "com.unity.modules.imgui": "1.0.0", 322 | "com.unity.modules.jsonserialize": "1.0.0", 323 | "com.unity.modules.uielementsnative": "1.0.0" 324 | } 325 | }, 326 | "com.unity.modules.uielementsnative": { 327 | "version": "1.0.0", 328 | "depth": 1, 329 | "source": "builtin", 330 | "dependencies": { 331 | "com.unity.modules.ui": "1.0.0", 332 | "com.unity.modules.imgui": "1.0.0", 333 | "com.unity.modules.jsonserialize": "1.0.0" 334 | } 335 | }, 336 | "com.unity.modules.umbra": { 337 | "version": "1.0.0", 338 | "depth": 0, 339 | "source": "builtin", 340 | "dependencies": {} 341 | }, 342 | "com.unity.modules.unityanalytics": { 343 | "version": "1.0.0", 344 | "depth": 0, 345 | "source": "builtin", 346 | "dependencies": { 347 | "com.unity.modules.unitywebrequest": "1.0.0", 348 | "com.unity.modules.jsonserialize": "1.0.0" 349 | } 350 | }, 351 | "com.unity.modules.unitywebrequest": { 352 | "version": "1.0.0", 353 | "depth": 0, 354 | "source": "builtin", 355 | "dependencies": {} 356 | }, 357 | "com.unity.modules.unitywebrequestassetbundle": { 358 | "version": "1.0.0", 359 | "depth": 0, 360 | "source": "builtin", 361 | "dependencies": { 362 | "com.unity.modules.assetbundle": "1.0.0", 363 | "com.unity.modules.unitywebrequest": "1.0.0" 364 | } 365 | }, 366 | "com.unity.modules.unitywebrequestaudio": { 367 | "version": "1.0.0", 368 | "depth": 0, 369 | "source": "builtin", 370 | "dependencies": { 371 | "com.unity.modules.unitywebrequest": "1.0.0", 372 | "com.unity.modules.audio": "1.0.0" 373 | } 374 | }, 375 | "com.unity.modules.unitywebrequesttexture": { 376 | "version": "1.0.0", 377 | "depth": 0, 378 | "source": "builtin", 379 | "dependencies": { 380 | "com.unity.modules.unitywebrequest": "1.0.0", 381 | "com.unity.modules.imageconversion": "1.0.0" 382 | } 383 | }, 384 | "com.unity.modules.unitywebrequestwww": { 385 | "version": "1.0.0", 386 | "depth": 0, 387 | "source": "builtin", 388 | "dependencies": { 389 | "com.unity.modules.unitywebrequest": "1.0.0", 390 | "com.unity.modules.unitywebrequestassetbundle": "1.0.0", 391 | "com.unity.modules.unitywebrequestaudio": "1.0.0", 392 | "com.unity.modules.audio": "1.0.0", 393 | "com.unity.modules.assetbundle": "1.0.0", 394 | "com.unity.modules.imageconversion": "1.0.0" 395 | } 396 | }, 397 | "com.unity.modules.vehicles": { 398 | "version": "1.0.0", 399 | "depth": 0, 400 | "source": "builtin", 401 | "dependencies": { 402 | "com.unity.modules.physics": "1.0.0" 403 | } 404 | }, 405 | "com.unity.modules.video": { 406 | "version": "1.0.0", 407 | "depth": 0, 408 | "source": "builtin", 409 | "dependencies": { 410 | "com.unity.modules.audio": "1.0.0", 411 | "com.unity.modules.ui": "1.0.0", 412 | "com.unity.modules.unitywebrequest": "1.0.0" 413 | } 414 | }, 415 | "com.unity.modules.vr": { 416 | "version": "1.0.0", 417 | "depth": 0, 418 | "source": "builtin", 419 | "dependencies": { 420 | "com.unity.modules.jsonserialize": "1.0.0", 421 | "com.unity.modules.physics": "1.0.0", 422 | "com.unity.modules.xr": "1.0.0" 423 | } 424 | }, 425 | "com.unity.modules.wind": { 426 | "version": "1.0.0", 427 | "depth": 0, 428 | "source": "builtin", 429 | "dependencies": {} 430 | }, 431 | "com.unity.modules.xr": { 432 | "version": "1.0.0", 433 | "depth": 0, 434 | "source": "builtin", 435 | "dependencies": { 436 | "com.unity.modules.physics": "1.0.0", 437 | "com.unity.modules.jsonserialize": "1.0.0", 438 | "com.unity.modules.subsystems": "1.0.0" 439 | } 440 | } 441 | } 442 | } 443 | -------------------------------------------------------------------------------- /ProjectSettings/AudioManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!11 &1 4 | AudioManager: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 2 7 | m_Volume: 1 8 | Rolloff Scale: 1 9 | Doppler Factor: 1 10 | Default Speaker Mode: 2 11 | m_SampleRate: 0 12 | m_DSPBufferSize: 1024 13 | m_VirtualVoiceCount: 512 14 | m_RealVoiceCount: 32 15 | m_SpatializerPlugin: 16 | m_AmbisonicDecoderPlugin: 17 | m_DisableAudio: 0 18 | m_VirtualizeEffects: 1 19 | m_RequestedDSPBufferSize: 0 20 | -------------------------------------------------------------------------------- /ProjectSettings/ClusterInputManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!236 &1 4 | ClusterInputManager: 5 | m_ObjectHideFlags: 0 6 | m_Inputs: [] 7 | -------------------------------------------------------------------------------- /ProjectSettings/DynamicsManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!55 &1 4 | PhysicsManager: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 13 7 | m_Gravity: {x: 0, y: -9.81, z: 0} 8 | m_DefaultMaterial: {fileID: 0} 9 | m_BounceThreshold: 2 10 | m_SleepThreshold: 0.005 11 | m_DefaultContactOffset: 0.01 12 | m_DefaultSolverIterations: 6 13 | m_DefaultSolverVelocityIterations: 1 14 | m_QueriesHitBackfaces: 0 15 | m_QueriesHitTriggers: 1 16 | m_EnableAdaptiveForce: 0 17 | m_ClothInterCollisionDistance: 0.1 18 | m_ClothInterCollisionStiffness: 0.2 19 | m_ContactsGeneration: 1 20 | m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 21 | m_AutoSimulation: 1 22 | m_AutoSyncTransforms: 0 23 | m_ReuseCollisionCallbacks: 1 24 | m_ClothInterCollisionSettingsToggle: 0 25 | m_ClothGravity: {x: 0, y: -9.81, z: 0} 26 | m_ContactPairsMode: 0 27 | m_BroadphaseType: 0 28 | m_WorldBounds: 29 | m_Center: {x: 0, y: 0, z: 0} 30 | m_Extent: {x: 250, y: 250, z: 250} 31 | m_WorldSubdivisions: 8 32 | m_FrictionType: 0 33 | m_EnableEnhancedDeterminism: 0 34 | m_EnableUnifiedHeightmaps: 1 35 | m_SolverType: 0 36 | m_DefaultMaxAngularSpeed: 50 37 | -------------------------------------------------------------------------------- /ProjectSettings/EditorBuildSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!1045 &1 4 | EditorBuildSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 2 7 | m_Scenes: 8 | - enabled: 1 9 | path: Assets/Scenes/SampleScene.unity 10 | guid: 2cda990e2423bbf4892e6590ba056729 11 | m_configObjects: {} 12 | -------------------------------------------------------------------------------- /ProjectSettings/EditorSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!159 &1 4 | EditorSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 10 7 | m_ExternalVersionControlSupport: Visible Meta Files 8 | m_SerializationMode: 2 9 | m_LineEndingsForNewScripts: 0 10 | m_DefaultBehaviorMode: 1 11 | m_PrefabRegularEnvironment: {fileID: 0} 12 | m_PrefabUIEnvironment: {fileID: 0} 13 | m_SpritePackerMode: 4 14 | m_SpritePackerPaddingPower: 1 15 | m_EtcTextureCompressorBehavior: 1 16 | m_EtcTextureFastCompressor: 1 17 | m_EtcTextureNormalCompressor: 2 18 | m_EtcTextureBestCompressor: 4 19 | m_ProjectGenerationIncludedExtensions: txt;xml;fnt;cd;asmdef;asmref;rsp 20 | m_ProjectGenerationRootNamespace: 21 | m_CollabEditorSettings: 22 | inProgressEnabled: 1 23 | m_EnableTextureStreamingInEditMode: 1 24 | m_EnableTextureStreamingInPlayMode: 1 25 | m_AsyncShaderCompilation: 1 26 | m_EnterPlayModeOptionsEnabled: 0 27 | m_EnterPlayModeOptions: 3 28 | m_ShowLightmapResolutionOverlay: 1 29 | m_UseLegacyProbeSampleCount: 0 30 | m_SerializeInlineMappingsOnOneLine: 1 31 | m_AssetPipelineMode: 1 32 | m_CacheServerMode: 0 33 | m_CacheServerEndpoint: 34 | m_CacheServerNamespacePrefix: default 35 | m_CacheServerEnableDownload: 1 36 | m_CacheServerEnableUpload: 1 37 | -------------------------------------------------------------------------------- /ProjectSettings/GraphicsSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!30 &1 4 | GraphicsSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 13 7 | m_Deferred: 8 | m_Mode: 1 9 | m_Shader: {fileID: 69, guid: 0000000000000000f000000000000000, type: 0} 10 | m_DeferredReflections: 11 | m_Mode: 1 12 | m_Shader: {fileID: 74, guid: 0000000000000000f000000000000000, type: 0} 13 | m_ScreenSpaceShadows: 14 | m_Mode: 1 15 | m_Shader: {fileID: 64, guid: 0000000000000000f000000000000000, type: 0} 16 | m_LegacyDeferred: 17 | m_Mode: 1 18 | m_Shader: {fileID: 63, guid: 0000000000000000f000000000000000, type: 0} 19 | m_DepthNormals: 20 | m_Mode: 1 21 | m_Shader: {fileID: 62, guid: 0000000000000000f000000000000000, type: 0} 22 | m_MotionVectors: 23 | m_Mode: 1 24 | m_Shader: {fileID: 75, guid: 0000000000000000f000000000000000, type: 0} 25 | m_LightHalo: 26 | m_Mode: 1 27 | m_Shader: {fileID: 105, guid: 0000000000000000f000000000000000, type: 0} 28 | m_LensFlare: 29 | m_Mode: 1 30 | m_Shader: {fileID: 102, guid: 0000000000000000f000000000000000, type: 0} 31 | m_VideoShadersIncludeMode: 2 32 | m_AlwaysIncludedShaders: 33 | - {fileID: 7, guid: 0000000000000000f000000000000000, type: 0} 34 | - {fileID: 15104, guid: 0000000000000000f000000000000000, type: 0} 35 | - {fileID: 15105, guid: 0000000000000000f000000000000000, type: 0} 36 | - {fileID: 15106, guid: 0000000000000000f000000000000000, type: 0} 37 | - {fileID: 10753, guid: 0000000000000000f000000000000000, type: 0} 38 | - {fileID: 10770, guid: 0000000000000000f000000000000000, type: 0} 39 | - {fileID: 10783, guid: 0000000000000000f000000000000000, type: 0} 40 | m_PreloadedShaders: [] 41 | m_SpritesDefaultMaterial: {fileID: 10754, guid: 0000000000000000f000000000000000, type: 0} 42 | m_CustomRenderPipeline: {fileID: 0} 43 | m_TransparencySortMode: 0 44 | m_TransparencySortAxis: {x: 0, y: 0, z: 1} 45 | m_DefaultRenderingPath: 1 46 | m_DefaultMobileRenderingPath: 1 47 | m_TierSettings: [] 48 | m_LightmapStripping: 0 49 | m_FogStripping: 0 50 | m_InstancingStripping: 0 51 | m_LightmapKeepPlain: 1 52 | m_LightmapKeepDirCombined: 1 53 | m_LightmapKeepDynamicPlain: 1 54 | m_LightmapKeepDynamicDirCombined: 1 55 | m_LightmapKeepShadowMask: 1 56 | m_LightmapKeepSubtractive: 1 57 | m_FogKeepLinear: 1 58 | m_FogKeepExp: 1 59 | m_FogKeepExp2: 1 60 | m_AlbedoSwatchInfos: [] 61 | m_LightsUseLinearIntensity: 0 62 | m_LightsUseColorTemperature: 0 63 | m_LogWhenShaderIsCompiled: 0 64 | -------------------------------------------------------------------------------- /ProjectSettings/InputManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!13 &1 4 | InputManager: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 2 7 | m_Axes: 8 | - serializedVersion: 3 9 | m_Name: Horizontal 10 | descriptiveName: 11 | descriptiveNegativeName: 12 | negativeButton: left 13 | positiveButton: right 14 | altNegativeButton: a 15 | altPositiveButton: d 16 | gravity: 3 17 | dead: 0.001 18 | sensitivity: 3 19 | snap: 1 20 | invert: 0 21 | type: 0 22 | axis: 0 23 | joyNum: 0 24 | - serializedVersion: 3 25 | m_Name: Vertical 26 | descriptiveName: 27 | descriptiveNegativeName: 28 | negativeButton: down 29 | positiveButton: up 30 | altNegativeButton: s 31 | altPositiveButton: w 32 | gravity: 3 33 | dead: 0.001 34 | sensitivity: 3 35 | snap: 1 36 | invert: 0 37 | type: 0 38 | axis: 0 39 | joyNum: 0 40 | - serializedVersion: 3 41 | m_Name: Fire1 42 | descriptiveName: 43 | descriptiveNegativeName: 44 | negativeButton: 45 | positiveButton: left ctrl 46 | altNegativeButton: 47 | altPositiveButton: mouse 0 48 | gravity: 1000 49 | dead: 0.001 50 | sensitivity: 1000 51 | snap: 0 52 | invert: 0 53 | type: 0 54 | axis: 0 55 | joyNum: 0 56 | - serializedVersion: 3 57 | m_Name: Fire2 58 | descriptiveName: 59 | descriptiveNegativeName: 60 | negativeButton: 61 | positiveButton: left alt 62 | altNegativeButton: 63 | altPositiveButton: mouse 1 64 | gravity: 1000 65 | dead: 0.001 66 | sensitivity: 1000 67 | snap: 0 68 | invert: 0 69 | type: 0 70 | axis: 0 71 | joyNum: 0 72 | - serializedVersion: 3 73 | m_Name: Fire3 74 | descriptiveName: 75 | descriptiveNegativeName: 76 | negativeButton: 77 | positiveButton: left shift 78 | altNegativeButton: 79 | altPositiveButton: mouse 2 80 | gravity: 1000 81 | dead: 0.001 82 | sensitivity: 1000 83 | snap: 0 84 | invert: 0 85 | type: 0 86 | axis: 0 87 | joyNum: 0 88 | - serializedVersion: 3 89 | m_Name: Jump 90 | descriptiveName: 91 | descriptiveNegativeName: 92 | negativeButton: 93 | positiveButton: space 94 | altNegativeButton: 95 | altPositiveButton: 96 | gravity: 1000 97 | dead: 0.001 98 | sensitivity: 1000 99 | snap: 0 100 | invert: 0 101 | type: 0 102 | axis: 0 103 | joyNum: 0 104 | - serializedVersion: 3 105 | m_Name: Mouse X 106 | descriptiveName: 107 | descriptiveNegativeName: 108 | negativeButton: 109 | positiveButton: 110 | altNegativeButton: 111 | altPositiveButton: 112 | gravity: 0 113 | dead: 0 114 | sensitivity: 0.1 115 | snap: 0 116 | invert: 0 117 | type: 1 118 | axis: 0 119 | joyNum: 0 120 | - serializedVersion: 3 121 | m_Name: Mouse Y 122 | descriptiveName: 123 | descriptiveNegativeName: 124 | negativeButton: 125 | positiveButton: 126 | altNegativeButton: 127 | altPositiveButton: 128 | gravity: 0 129 | dead: 0 130 | sensitivity: 0.1 131 | snap: 0 132 | invert: 0 133 | type: 1 134 | axis: 1 135 | joyNum: 0 136 | - serializedVersion: 3 137 | m_Name: Mouse ScrollWheel 138 | descriptiveName: 139 | descriptiveNegativeName: 140 | negativeButton: 141 | positiveButton: 142 | altNegativeButton: 143 | altPositiveButton: 144 | gravity: 0 145 | dead: 0 146 | sensitivity: 0.1 147 | snap: 0 148 | invert: 0 149 | type: 1 150 | axis: 2 151 | joyNum: 0 152 | - serializedVersion: 3 153 | m_Name: Horizontal 154 | descriptiveName: 155 | descriptiveNegativeName: 156 | negativeButton: 157 | positiveButton: 158 | altNegativeButton: 159 | altPositiveButton: 160 | gravity: 0 161 | dead: 0.19 162 | sensitivity: 1 163 | snap: 0 164 | invert: 0 165 | type: 2 166 | axis: 0 167 | joyNum: 0 168 | - serializedVersion: 3 169 | m_Name: Vertical 170 | descriptiveName: 171 | descriptiveNegativeName: 172 | negativeButton: 173 | positiveButton: 174 | altNegativeButton: 175 | altPositiveButton: 176 | gravity: 0 177 | dead: 0.19 178 | sensitivity: 1 179 | snap: 0 180 | invert: 1 181 | type: 2 182 | axis: 1 183 | joyNum: 0 184 | - serializedVersion: 3 185 | m_Name: Fire1 186 | descriptiveName: 187 | descriptiveNegativeName: 188 | negativeButton: 189 | positiveButton: joystick button 0 190 | altNegativeButton: 191 | altPositiveButton: 192 | gravity: 1000 193 | dead: 0.001 194 | sensitivity: 1000 195 | snap: 0 196 | invert: 0 197 | type: 0 198 | axis: 0 199 | joyNum: 0 200 | - serializedVersion: 3 201 | m_Name: Fire2 202 | descriptiveName: 203 | descriptiveNegativeName: 204 | negativeButton: 205 | positiveButton: joystick button 1 206 | altNegativeButton: 207 | altPositiveButton: 208 | gravity: 1000 209 | dead: 0.001 210 | sensitivity: 1000 211 | snap: 0 212 | invert: 0 213 | type: 0 214 | axis: 0 215 | joyNum: 0 216 | - serializedVersion: 3 217 | m_Name: Fire3 218 | descriptiveName: 219 | descriptiveNegativeName: 220 | negativeButton: 221 | positiveButton: joystick button 2 222 | altNegativeButton: 223 | altPositiveButton: 224 | gravity: 1000 225 | dead: 0.001 226 | sensitivity: 1000 227 | snap: 0 228 | invert: 0 229 | type: 0 230 | axis: 0 231 | joyNum: 0 232 | - serializedVersion: 3 233 | m_Name: Jump 234 | descriptiveName: 235 | descriptiveNegativeName: 236 | negativeButton: 237 | positiveButton: joystick button 3 238 | altNegativeButton: 239 | altPositiveButton: 240 | gravity: 1000 241 | dead: 0.001 242 | sensitivity: 1000 243 | snap: 0 244 | invert: 0 245 | type: 0 246 | axis: 0 247 | joyNum: 0 248 | - serializedVersion: 3 249 | m_Name: Submit 250 | descriptiveName: 251 | descriptiveNegativeName: 252 | negativeButton: 253 | positiveButton: return 254 | altNegativeButton: 255 | altPositiveButton: joystick button 0 256 | gravity: 1000 257 | dead: 0.001 258 | sensitivity: 1000 259 | snap: 0 260 | invert: 0 261 | type: 0 262 | axis: 0 263 | joyNum: 0 264 | - serializedVersion: 3 265 | m_Name: Submit 266 | descriptiveName: 267 | descriptiveNegativeName: 268 | negativeButton: 269 | positiveButton: enter 270 | altNegativeButton: 271 | altPositiveButton: space 272 | gravity: 1000 273 | dead: 0.001 274 | sensitivity: 1000 275 | snap: 0 276 | invert: 0 277 | type: 0 278 | axis: 0 279 | joyNum: 0 280 | - serializedVersion: 3 281 | m_Name: Cancel 282 | descriptiveName: 283 | descriptiveNegativeName: 284 | negativeButton: 285 | positiveButton: escape 286 | altNegativeButton: 287 | altPositiveButton: joystick button 1 288 | gravity: 1000 289 | dead: 0.001 290 | sensitivity: 1000 291 | snap: 0 292 | invert: 0 293 | type: 0 294 | axis: 0 295 | joyNum: 0 296 | - serializedVersion: 3 297 | m_Name: Enable Debug Button 1 298 | descriptiveName: 299 | descriptiveNegativeName: 300 | negativeButton: 301 | positiveButton: left ctrl 302 | altNegativeButton: 303 | altPositiveButton: joystick button 8 304 | gravity: 0 305 | dead: 0 306 | sensitivity: 0 307 | snap: 0 308 | invert: 0 309 | type: 0 310 | axis: 0 311 | joyNum: 0 312 | - serializedVersion: 3 313 | m_Name: Enable Debug Button 2 314 | descriptiveName: 315 | descriptiveNegativeName: 316 | negativeButton: 317 | positiveButton: backspace 318 | altNegativeButton: 319 | altPositiveButton: joystick button 9 320 | gravity: 0 321 | dead: 0 322 | sensitivity: 0 323 | snap: 0 324 | invert: 0 325 | type: 0 326 | axis: 0 327 | joyNum: 0 328 | - serializedVersion: 3 329 | m_Name: Debug Reset 330 | descriptiveName: 331 | descriptiveNegativeName: 332 | negativeButton: 333 | positiveButton: left alt 334 | altNegativeButton: 335 | altPositiveButton: joystick button 1 336 | gravity: 0 337 | dead: 0 338 | sensitivity: 0 339 | snap: 0 340 | invert: 0 341 | type: 0 342 | axis: 0 343 | joyNum: 0 344 | - serializedVersion: 3 345 | m_Name: Debug Next 346 | descriptiveName: 347 | descriptiveNegativeName: 348 | negativeButton: 349 | positiveButton: page down 350 | altNegativeButton: 351 | altPositiveButton: joystick button 5 352 | gravity: 0 353 | dead: 0 354 | sensitivity: 0 355 | snap: 0 356 | invert: 0 357 | type: 0 358 | axis: 0 359 | joyNum: 0 360 | - serializedVersion: 3 361 | m_Name: Debug Previous 362 | descriptiveName: 363 | descriptiveNegativeName: 364 | negativeButton: 365 | positiveButton: page up 366 | altNegativeButton: 367 | altPositiveButton: joystick button 4 368 | gravity: 0 369 | dead: 0 370 | sensitivity: 0 371 | snap: 0 372 | invert: 0 373 | type: 0 374 | axis: 0 375 | joyNum: 0 376 | - serializedVersion: 3 377 | m_Name: Debug Validate 378 | descriptiveName: 379 | descriptiveNegativeName: 380 | negativeButton: 381 | positiveButton: return 382 | altNegativeButton: 383 | altPositiveButton: joystick button 0 384 | gravity: 0 385 | dead: 0 386 | sensitivity: 0 387 | snap: 0 388 | invert: 0 389 | type: 0 390 | axis: 0 391 | joyNum: 0 392 | - serializedVersion: 3 393 | m_Name: Debug Persistent 394 | descriptiveName: 395 | descriptiveNegativeName: 396 | negativeButton: 397 | positiveButton: right shift 398 | altNegativeButton: 399 | altPositiveButton: joystick button 2 400 | gravity: 0 401 | dead: 0 402 | sensitivity: 0 403 | snap: 0 404 | invert: 0 405 | type: 0 406 | axis: 0 407 | joyNum: 0 408 | - serializedVersion: 3 409 | m_Name: Debug Multiplier 410 | descriptiveName: 411 | descriptiveNegativeName: 412 | negativeButton: 413 | positiveButton: left shift 414 | altNegativeButton: 415 | altPositiveButton: joystick button 3 416 | gravity: 0 417 | dead: 0 418 | sensitivity: 0 419 | snap: 0 420 | invert: 0 421 | type: 0 422 | axis: 0 423 | joyNum: 0 424 | - serializedVersion: 3 425 | m_Name: Debug Horizontal 426 | descriptiveName: 427 | descriptiveNegativeName: 428 | negativeButton: left 429 | positiveButton: right 430 | altNegativeButton: 431 | altPositiveButton: 432 | gravity: 1000 433 | dead: 0.001 434 | sensitivity: 1000 435 | snap: 0 436 | invert: 0 437 | type: 0 438 | axis: 0 439 | joyNum: 0 440 | - serializedVersion: 3 441 | m_Name: Debug Vertical 442 | descriptiveName: 443 | descriptiveNegativeName: 444 | negativeButton: down 445 | positiveButton: up 446 | altNegativeButton: 447 | altPositiveButton: 448 | gravity: 1000 449 | dead: 0.001 450 | sensitivity: 1000 451 | snap: 0 452 | invert: 0 453 | type: 0 454 | axis: 0 455 | joyNum: 0 456 | - serializedVersion: 3 457 | m_Name: Debug Vertical 458 | descriptiveName: 459 | descriptiveNegativeName: 460 | negativeButton: down 461 | positiveButton: up 462 | altNegativeButton: 463 | altPositiveButton: 464 | gravity: 1000 465 | dead: 0.001 466 | sensitivity: 1000 467 | snap: 0 468 | invert: 0 469 | type: 2 470 | axis: 6 471 | joyNum: 0 472 | - serializedVersion: 3 473 | m_Name: Debug Horizontal 474 | descriptiveName: 475 | descriptiveNegativeName: 476 | negativeButton: left 477 | positiveButton: right 478 | altNegativeButton: 479 | altPositiveButton: 480 | gravity: 1000 481 | dead: 0.001 482 | sensitivity: 1000 483 | snap: 0 484 | invert: 0 485 | type: 2 486 | axis: 5 487 | joyNum: 0 488 | -------------------------------------------------------------------------------- /ProjectSettings/NavMeshAreas.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!126 &1 4 | NavMeshProjectSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 2 7 | areas: 8 | - name: Walkable 9 | cost: 1 10 | - name: Not Walkable 11 | cost: 1 12 | - name: Jump 13 | cost: 2 14 | - name: 15 | cost: 1 16 | - name: 17 | cost: 1 18 | - name: 19 | cost: 1 20 | - name: 21 | cost: 1 22 | - name: 23 | cost: 1 24 | - name: 25 | cost: 1 26 | - name: 27 | cost: 1 28 | - name: 29 | cost: 1 30 | - name: 31 | cost: 1 32 | - name: 33 | cost: 1 34 | - name: 35 | cost: 1 36 | - name: 37 | cost: 1 38 | - name: 39 | cost: 1 40 | - name: 41 | cost: 1 42 | - name: 43 | cost: 1 44 | - name: 45 | cost: 1 46 | - name: 47 | cost: 1 48 | - name: 49 | cost: 1 50 | - name: 51 | cost: 1 52 | - name: 53 | cost: 1 54 | - name: 55 | cost: 1 56 | - name: 57 | cost: 1 58 | - name: 59 | cost: 1 60 | - name: 61 | cost: 1 62 | - name: 63 | cost: 1 64 | - name: 65 | cost: 1 66 | - name: 67 | cost: 1 68 | - name: 69 | cost: 1 70 | - name: 71 | cost: 1 72 | m_LastAgentTypeID: -887442657 73 | m_Settings: 74 | - serializedVersion: 2 75 | agentTypeID: 0 76 | agentRadius: 0.5 77 | agentHeight: 2 78 | agentSlope: 45 79 | agentClimb: 0.75 80 | ledgeDropHeight: 0 81 | maxJumpAcrossDistance: 0 82 | minRegionArea: 2 83 | manualCellSize: 0 84 | cellSize: 0.16666667 85 | manualTileSize: 0 86 | tileSize: 256 87 | accuratePlacement: 0 88 | debug: 89 | m_Flags: 0 90 | m_SettingNames: 91 | - Humanoid 92 | -------------------------------------------------------------------------------- /ProjectSettings/NetworkManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!149 &1 4 | NetworkManager: 5 | m_ObjectHideFlags: 0 6 | m_DebugLevel: 0 7 | m_Sendrate: 15 8 | m_AssetToPrefab: {} 9 | -------------------------------------------------------------------------------- /ProjectSettings/PackageManagerSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!114 &1 4 | MonoBehaviour: 5 | m_ObjectHideFlags: 61 6 | m_CorrespondingSourceObject: {fileID: 0} 7 | m_PrefabInstance: {fileID: 0} 8 | m_PrefabAsset: {fileID: 0} 9 | m_GameObject: {fileID: 0} 10 | m_Enabled: 1 11 | m_EditorHideFlags: 0 12 | m_Script: {fileID: 13964, guid: 0000000000000000e000000000000000, type: 0} 13 | m_Name: 14 | m_EditorClassIdentifier: 15 | m_EnablePreviewPackages: 0 16 | m_EnablePackageDependencies: 0 17 | m_AdvancedSettingsExpanded: 1 18 | m_ScopedRegistriesSettingsExpanded: 1 19 | oneTimeWarningShown: 0 20 | m_Registries: 21 | - m_Id: main 22 | m_Name: 23 | m_Url: https://packages.unity.com 24 | m_Scopes: [] 25 | m_IsDefault: 1 26 | m_Capabilities: 7 27 | m_UserSelectedRegistryName: 28 | m_UserAddingNewScopedRegistry: 0 29 | m_RegistryInfoDraft: 30 | m_ErrorMessage: 31 | m_Original: 32 | m_Id: 33 | m_Name: 34 | m_Url: 35 | m_Scopes: [] 36 | m_IsDefault: 0 37 | m_Capabilities: 0 38 | m_Modified: 0 39 | m_Name: 40 | m_Url: 41 | m_Scopes: 42 | - 43 | m_SelectedScopeIndex: 0 44 | -------------------------------------------------------------------------------- /ProjectSettings/Physics2DSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!19 &1 4 | Physics2DSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 5 7 | m_Gravity: {x: 0, y: -9.81} 8 | m_DefaultMaterial: {fileID: 0} 9 | m_VelocityIterations: 8 10 | m_PositionIterations: 3 11 | m_VelocityThreshold: 1 12 | m_MaxLinearCorrection: 0.2 13 | m_MaxAngularCorrection: 8 14 | m_MaxTranslationSpeed: 100 15 | m_MaxRotationSpeed: 360 16 | m_BaumgarteScale: 0.2 17 | m_BaumgarteTimeOfImpactScale: 0.75 18 | m_TimeToSleep: 0.5 19 | m_LinearSleepTolerance: 0.01 20 | m_AngularSleepTolerance: 2 21 | m_DefaultContactOffset: 0.01 22 | m_JobOptions: 23 | serializedVersion: 2 24 | useMultithreading: 0 25 | useConsistencySorting: 0 26 | m_InterpolationPosesPerJob: 100 27 | m_NewContactsPerJob: 30 28 | m_CollideContactsPerJob: 100 29 | m_ClearFlagsPerJob: 200 30 | m_ClearBodyForcesPerJob: 200 31 | m_SyncDiscreteFixturesPerJob: 50 32 | m_SyncContinuousFixturesPerJob: 50 33 | m_FindNearestContactsPerJob: 100 34 | m_UpdateTriggerContactsPerJob: 100 35 | m_IslandSolverCostThreshold: 100 36 | m_IslandSolverBodyCostScale: 1 37 | m_IslandSolverContactCostScale: 10 38 | m_IslandSolverJointCostScale: 10 39 | m_IslandSolverBodiesPerJob: 50 40 | m_IslandSolverContactsPerJob: 50 41 | m_SimulationMode: 0 42 | m_QueriesHitTriggers: 1 43 | m_QueriesStartInColliders: 1 44 | m_CallbacksOnDisable: 1 45 | m_ReuseCollisionCallbacks: 1 46 | m_AutoSyncTransforms: 0 47 | m_AlwaysShowColliders: 0 48 | m_ShowColliderSleep: 1 49 | m_ShowColliderContacts: 0 50 | m_ShowColliderAABB: 0 51 | m_ContactArrowScale: 0.2 52 | m_ColliderAwakeColor: {r: 0.5686275, g: 0.95686275, b: 0.54509807, a: 0.7529412} 53 | m_ColliderAsleepColor: {r: 0.5686275, g: 0.95686275, b: 0.54509807, a: 0.36078432} 54 | m_ColliderContactColor: {r: 1, g: 0, b: 1, a: 0.6862745} 55 | m_ColliderAABBColor: {r: 1, g: 1, b: 0, a: 0.2509804} 56 | m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 57 | -------------------------------------------------------------------------------- /ProjectSettings/PresetManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!1386491679 &1 4 | PresetManager: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 2 7 | m_DefaultPresets: {} 8 | -------------------------------------------------------------------------------- /ProjectSettings/ProjectSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!129 &1 4 | PlayerSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 22 7 | productGUID: 630410c13676646df8aa7294c8571a45 8 | AndroidProfiler: 0 9 | AndroidFilterTouchesWhenObscured: 0 10 | AndroidEnableSustainedPerformanceMode: 0 11 | defaultScreenOrientation: 4 12 | targetDevice: 2 13 | useOnDemandResources: 0 14 | accelerometerFrequency: 60 15 | companyName: DefaultCompany 16 | productName: UnityTextureHunter 17 | defaultCursor: {fileID: 0} 18 | cursorHotspot: {x: 0, y: 0} 19 | m_SplashScreenBackgroundColor: {r: 0.13725491, g: 0.12156863, b: 0.1254902, a: 1} 20 | m_ShowUnitySplashScreen: 1 21 | m_ShowUnitySplashLogo: 1 22 | m_SplashScreenOverlayOpacity: 1 23 | m_SplashScreenAnimation: 1 24 | m_SplashScreenLogoStyle: 1 25 | m_SplashScreenDrawMode: 0 26 | m_SplashScreenBackgroundAnimationZoom: 1 27 | m_SplashScreenLogoAnimationZoom: 1 28 | m_SplashScreenBackgroundLandscapeAspect: 1 29 | m_SplashScreenBackgroundPortraitAspect: 1 30 | m_SplashScreenBackgroundLandscapeUvs: 31 | serializedVersion: 2 32 | x: 0 33 | y: 0 34 | width: 1 35 | height: 1 36 | m_SplashScreenBackgroundPortraitUvs: 37 | serializedVersion: 2 38 | x: 0 39 | y: 0 40 | width: 1 41 | height: 1 42 | m_SplashScreenLogos: [] 43 | m_VirtualRealitySplashScreen: {fileID: 0} 44 | m_HolographicTrackingLossScreen: {fileID: 0} 45 | defaultScreenWidth: 1920 46 | defaultScreenHeight: 1080 47 | defaultScreenWidthWeb: 960 48 | defaultScreenHeightWeb: 600 49 | m_StereoRenderingPath: 0 50 | m_ActiveColorSpace: 0 51 | m_MTRendering: 1 52 | mipStripping: 0 53 | numberOfMipsStripped: 0 54 | m_StackTraceTypes: 010000000100000001000000010000000100000001000000 55 | iosShowActivityIndicatorOnLoading: -1 56 | androidShowActivityIndicatorOnLoading: -1 57 | iosUseCustomAppBackgroundBehavior: 0 58 | iosAllowHTTPDownload: 1 59 | allowedAutorotateToPortrait: 1 60 | allowedAutorotateToPortraitUpsideDown: 1 61 | allowedAutorotateToLandscapeRight: 1 62 | allowedAutorotateToLandscapeLeft: 1 63 | useOSAutorotation: 1 64 | use32BitDisplayBuffer: 1 65 | preserveFramebufferAlpha: 0 66 | disableDepthAndStencilBuffers: 0 67 | androidStartInFullscreen: 1 68 | androidRenderOutsideSafeArea: 1 69 | androidUseSwappy: 1 70 | androidBlitType: 0 71 | androidResizableWindow: 0 72 | androidDefaultWindowWidth: 1920 73 | androidDefaultWindowHeight: 1080 74 | androidMinimumWindowWidth: 400 75 | androidMinimumWindowHeight: 300 76 | androidFullscreenMode: 1 77 | defaultIsNativeResolution: 1 78 | macRetinaSupport: 1 79 | runInBackground: 0 80 | captureSingleScreen: 0 81 | muteOtherAudioSources: 0 82 | Prepare IOS For Recording: 0 83 | Force IOS Speakers When Recording: 0 84 | deferSystemGesturesMode: 0 85 | hideHomeButton: 0 86 | submitAnalytics: 1 87 | usePlayerLog: 1 88 | bakeCollisionMeshes: 0 89 | forceSingleInstance: 0 90 | useFlipModelSwapchain: 1 91 | resizableWindow: 0 92 | useMacAppStoreValidation: 0 93 | macAppStoreCategory: public.app-category.games 94 | gpuSkinning: 0 95 | xboxPIXTextureCapture: 0 96 | xboxEnableAvatar: 0 97 | xboxEnableKinect: 0 98 | xboxEnableKinectAutoTracking: 0 99 | xboxEnableFitness: 0 100 | visibleInBackground: 1 101 | allowFullscreenSwitch: 1 102 | fullscreenMode: 1 103 | xboxSpeechDB: 0 104 | xboxEnableHeadOrientation: 0 105 | xboxEnableGuest: 0 106 | xboxEnablePIXSampling: 0 107 | metalFramebufferOnly: 0 108 | xboxOneResolution: 0 109 | xboxOneSResolution: 0 110 | xboxOneXResolution: 3 111 | xboxOneMonoLoggingLevel: 0 112 | xboxOneLoggingLevel: 1 113 | xboxOneDisableEsram: 0 114 | xboxOneEnableTypeOptimization: 0 115 | xboxOnePresentImmediateThreshold: 0 116 | switchQueueCommandMemory: 1048576 117 | switchQueueControlMemory: 16384 118 | switchQueueComputeMemory: 262144 119 | switchNVNShaderPoolsGranularity: 33554432 120 | switchNVNDefaultPoolsGranularity: 16777216 121 | switchNVNOtherPoolsGranularity: 16777216 122 | switchNVNMaxPublicTextureIDCount: 0 123 | switchNVNMaxPublicSamplerIDCount: 0 124 | stadiaPresentMode: 0 125 | stadiaTargetFramerate: 0 126 | vulkanNumSwapchainBuffers: 3 127 | vulkanEnableSetSRGBWrite: 0 128 | vulkanEnablePreTransform: 0 129 | vulkanEnableLateAcquireNextImage: 0 130 | vulkanEnableCommandBufferRecycling: 1 131 | m_SupportedAspectRatios: 132 | 4:3: 1 133 | 5:4: 1 134 | 16:10: 1 135 | 16:9: 1 136 | Others: 1 137 | bundleVersion: 1.0 138 | preloadedAssets: [] 139 | metroInputSource: 0 140 | wsaTransparentSwapchain: 0 141 | m_HolographicPauseOnTrackingLoss: 1 142 | xboxOneDisableKinectGpuReservation: 1 143 | xboxOneEnable7thCore: 1 144 | vrSettings: 145 | enable360StereoCapture: 0 146 | isWsaHolographicRemotingEnabled: 0 147 | enableFrameTimingStats: 0 148 | useHDRDisplay: 0 149 | D3DHDRBitDepth: 0 150 | m_ColorGamuts: 00000000 151 | targetPixelDensity: 30 152 | resolutionScalingMode: 0 153 | androidSupportedAspectRatio: 1 154 | androidMaxAspectRatio: 2.1 155 | applicationIdentifier: {} 156 | buildNumber: 157 | Standalone: 0 158 | iPhone: 0 159 | tvOS: 0 160 | overrideDefaultApplicationIdentifier: 0 161 | AndroidBundleVersionCode: 1 162 | AndroidMinSdkVersion: 19 163 | AndroidTargetSdkVersion: 0 164 | AndroidPreferredInstallLocation: 1 165 | aotOptions: 166 | stripEngineCode: 1 167 | iPhoneStrippingLevel: 0 168 | iPhoneScriptCallOptimization: 0 169 | ForceInternetPermission: 0 170 | ForceSDCardPermission: 0 171 | CreateWallpaper: 0 172 | APKExpansionFiles: 0 173 | keepLoadedShadersAlive: 0 174 | StripUnusedMeshComponents: 0 175 | VertexChannelCompressionMask: 4054 176 | iPhoneSdkVersion: 988 177 | iOSTargetOSVersionString: 11.0 178 | tvOSSdkVersion: 0 179 | tvOSRequireExtendedGameController: 0 180 | tvOSTargetOSVersionString: 11.0 181 | uIPrerenderedIcon: 0 182 | uIRequiresPersistentWiFi: 0 183 | uIRequiresFullScreen: 1 184 | uIStatusBarHidden: 1 185 | uIExitOnSuspend: 0 186 | uIStatusBarStyle: 0 187 | appleTVSplashScreen: {fileID: 0} 188 | appleTVSplashScreen2x: {fileID: 0} 189 | tvOSSmallIconLayers: [] 190 | tvOSSmallIconLayers2x: [] 191 | tvOSLargeIconLayers: [] 192 | tvOSLargeIconLayers2x: [] 193 | tvOSTopShelfImageLayers: [] 194 | tvOSTopShelfImageLayers2x: [] 195 | tvOSTopShelfImageWideLayers: [] 196 | tvOSTopShelfImageWideLayers2x: [] 197 | iOSLaunchScreenType: 0 198 | iOSLaunchScreenPortrait: {fileID: 0} 199 | iOSLaunchScreenLandscape: {fileID: 0} 200 | iOSLaunchScreenBackgroundColor: 201 | serializedVersion: 2 202 | rgba: 0 203 | iOSLaunchScreenFillPct: 100 204 | iOSLaunchScreenSize: 100 205 | iOSLaunchScreenCustomXibPath: 206 | iOSLaunchScreeniPadType: 0 207 | iOSLaunchScreeniPadImage: {fileID: 0} 208 | iOSLaunchScreeniPadBackgroundColor: 209 | serializedVersion: 2 210 | rgba: 0 211 | iOSLaunchScreeniPadFillPct: 100 212 | iOSLaunchScreeniPadSize: 100 213 | iOSLaunchScreeniPadCustomXibPath: 214 | iOSLaunchScreenCustomStoryboardPath: 215 | iOSLaunchScreeniPadCustomStoryboardPath: 216 | iOSDeviceRequirements: [] 217 | iOSURLSchemes: [] 218 | iOSBackgroundModes: 0 219 | iOSMetalForceHardShadows: 0 220 | metalEditorSupport: 1 221 | metalAPIValidation: 1 222 | iOSRenderExtraFrameOnPause: 0 223 | iosCopyPluginsCodeInsteadOfSymlink: 0 224 | appleDeveloperTeamID: 225 | iOSManualSigningProvisioningProfileID: 226 | tvOSManualSigningProvisioningProfileID: 227 | iOSManualSigningProvisioningProfileType: 0 228 | tvOSManualSigningProvisioningProfileType: 0 229 | appleEnableAutomaticSigning: 0 230 | iOSRequireARKit: 0 231 | iOSAutomaticallyDetectAndAddCapabilities: 1 232 | appleEnableProMotion: 0 233 | shaderPrecisionModel: 0 234 | clonedFromGUID: 10ad67313f4034357812315f3c407484 235 | templatePackageId: com.unity.template.2d@5.0.0 236 | templateDefaultScene: Assets/Scenes/SampleScene.unity 237 | useCustomMainManifest: 0 238 | useCustomLauncherManifest: 0 239 | useCustomMainGradleTemplate: 0 240 | useCustomLauncherGradleManifest: 0 241 | useCustomBaseGradleTemplate: 0 242 | useCustomGradlePropertiesTemplate: 0 243 | useCustomProguardFile: 0 244 | AndroidTargetArchitectures: 1 245 | AndroidTargetDevices: 0 246 | AndroidSplashScreenScale: 0 247 | androidSplashScreen: {fileID: 0} 248 | AndroidKeystoreName: 249 | AndroidKeyaliasName: 250 | AndroidBuildApkPerCpuArchitecture: 0 251 | AndroidTVCompatibility: 0 252 | AndroidIsGame: 1 253 | AndroidEnableTango: 0 254 | androidEnableBanner: 1 255 | androidUseLowAccuracyLocation: 0 256 | androidUseCustomKeystore: 0 257 | m_AndroidBanners: 258 | - width: 320 259 | height: 180 260 | banner: {fileID: 0} 261 | androidGamepadSupportLevel: 0 262 | chromeosInputEmulation: 1 263 | AndroidMinifyWithR8: 0 264 | AndroidMinifyRelease: 0 265 | AndroidMinifyDebug: 0 266 | AndroidValidateAppBundleSize: 1 267 | AndroidAppBundleSizeToValidate: 150 268 | m_BuildTargetIcons: [] 269 | m_BuildTargetPlatformIcons: [] 270 | m_BuildTargetBatching: [] 271 | m_BuildTargetGraphicsJobs: 272 | - m_BuildTarget: MacStandaloneSupport 273 | m_GraphicsJobs: 0 274 | - m_BuildTarget: Switch 275 | m_GraphicsJobs: 0 276 | - m_BuildTarget: MetroSupport 277 | m_GraphicsJobs: 0 278 | - m_BuildTarget: AppleTVSupport 279 | m_GraphicsJobs: 0 280 | - m_BuildTarget: BJMSupport 281 | m_GraphicsJobs: 0 282 | - m_BuildTarget: LinuxStandaloneSupport 283 | m_GraphicsJobs: 0 284 | - m_BuildTarget: PS4Player 285 | m_GraphicsJobs: 0 286 | - m_BuildTarget: iOSSupport 287 | m_GraphicsJobs: 0 288 | - m_BuildTarget: WindowsStandaloneSupport 289 | m_GraphicsJobs: 0 290 | - m_BuildTarget: XboxOnePlayer 291 | m_GraphicsJobs: 0 292 | - m_BuildTarget: LuminSupport 293 | m_GraphicsJobs: 0 294 | - m_BuildTarget: AndroidPlayer 295 | m_GraphicsJobs: 0 296 | - m_BuildTarget: WebGLSupport 297 | m_GraphicsJobs: 0 298 | m_BuildTargetGraphicsJobMode: [] 299 | m_BuildTargetGraphicsAPIs: 300 | - m_BuildTarget: AndroidPlayer 301 | m_APIs: 150000000b000000 302 | m_Automatic: 0 303 | - m_BuildTarget: iOSSupport 304 | m_APIs: 10000000 305 | m_Automatic: 1 306 | m_BuildTargetVRSettings: [] 307 | openGLRequireES31: 0 308 | openGLRequireES31AEP: 0 309 | openGLRequireES32: 0 310 | m_TemplateCustomTags: {} 311 | mobileMTRendering: 312 | Android: 1 313 | iPhone: 1 314 | tvOS: 1 315 | m_BuildTargetGroupLightmapEncodingQuality: [] 316 | m_BuildTargetGroupLightmapSettings: [] 317 | m_BuildTargetNormalMapEncoding: [] 318 | playModeTestRunnerEnabled: 0 319 | runPlayModeTestAsEditModeTest: 0 320 | actionOnDotNetUnhandledException: 1 321 | enableInternalProfiler: 0 322 | logObjCUncaughtExceptions: 1 323 | enableCrashReportAPI: 0 324 | cameraUsageDescription: 325 | locationUsageDescription: 326 | microphoneUsageDescription: 327 | bluetoothUsageDescription: 328 | switchNMETAOverride: 329 | switchNetLibKey: 330 | switchSocketMemoryPoolSize: 6144 331 | switchSocketAllocatorPoolSize: 128 332 | switchSocketConcurrencyLimit: 14 333 | switchScreenResolutionBehavior: 2 334 | switchUseCPUProfiler: 0 335 | switchUseGOLDLinker: 0 336 | switchApplicationID: 0x01004b9000490000 337 | switchNSODependencies: 338 | switchTitleNames_0: 339 | switchTitleNames_1: 340 | switchTitleNames_2: 341 | switchTitleNames_3: 342 | switchTitleNames_4: 343 | switchTitleNames_5: 344 | switchTitleNames_6: 345 | switchTitleNames_7: 346 | switchTitleNames_8: 347 | switchTitleNames_9: 348 | switchTitleNames_10: 349 | switchTitleNames_11: 350 | switchTitleNames_12: 351 | switchTitleNames_13: 352 | switchTitleNames_14: 353 | switchTitleNames_15: 354 | switchPublisherNames_0: 355 | switchPublisherNames_1: 356 | switchPublisherNames_2: 357 | switchPublisherNames_3: 358 | switchPublisherNames_4: 359 | switchPublisherNames_5: 360 | switchPublisherNames_6: 361 | switchPublisherNames_7: 362 | switchPublisherNames_8: 363 | switchPublisherNames_9: 364 | switchPublisherNames_10: 365 | switchPublisherNames_11: 366 | switchPublisherNames_12: 367 | switchPublisherNames_13: 368 | switchPublisherNames_14: 369 | switchPublisherNames_15: 370 | switchIcons_0: {fileID: 0} 371 | switchIcons_1: {fileID: 0} 372 | switchIcons_2: {fileID: 0} 373 | switchIcons_3: {fileID: 0} 374 | switchIcons_4: {fileID: 0} 375 | switchIcons_5: {fileID: 0} 376 | switchIcons_6: {fileID: 0} 377 | switchIcons_7: {fileID: 0} 378 | switchIcons_8: {fileID: 0} 379 | switchIcons_9: {fileID: 0} 380 | switchIcons_10: {fileID: 0} 381 | switchIcons_11: {fileID: 0} 382 | switchIcons_12: {fileID: 0} 383 | switchIcons_13: {fileID: 0} 384 | switchIcons_14: {fileID: 0} 385 | switchIcons_15: {fileID: 0} 386 | switchSmallIcons_0: {fileID: 0} 387 | switchSmallIcons_1: {fileID: 0} 388 | switchSmallIcons_2: {fileID: 0} 389 | switchSmallIcons_3: {fileID: 0} 390 | switchSmallIcons_4: {fileID: 0} 391 | switchSmallIcons_5: {fileID: 0} 392 | switchSmallIcons_6: {fileID: 0} 393 | switchSmallIcons_7: {fileID: 0} 394 | switchSmallIcons_8: {fileID: 0} 395 | switchSmallIcons_9: {fileID: 0} 396 | switchSmallIcons_10: {fileID: 0} 397 | switchSmallIcons_11: {fileID: 0} 398 | switchSmallIcons_12: {fileID: 0} 399 | switchSmallIcons_13: {fileID: 0} 400 | switchSmallIcons_14: {fileID: 0} 401 | switchSmallIcons_15: {fileID: 0} 402 | switchManualHTML: 403 | switchAccessibleURLs: 404 | switchLegalInformation: 405 | switchMainThreadStackSize: 1048576 406 | switchPresenceGroupId: 407 | switchLogoHandling: 0 408 | switchReleaseVersion: 0 409 | switchDisplayVersion: 1.0.0 410 | switchStartupUserAccount: 0 411 | switchTouchScreenUsage: 0 412 | switchSupportedLanguagesMask: 0 413 | switchLogoType: 0 414 | switchApplicationErrorCodeCategory: 415 | switchUserAccountSaveDataSize: 0 416 | switchUserAccountSaveDataJournalSize: 0 417 | switchApplicationAttribute: 0 418 | switchCardSpecSize: -1 419 | switchCardSpecClock: -1 420 | switchRatingsMask: 0 421 | switchRatingsInt_0: 0 422 | switchRatingsInt_1: 0 423 | switchRatingsInt_2: 0 424 | switchRatingsInt_3: 0 425 | switchRatingsInt_4: 0 426 | switchRatingsInt_5: 0 427 | switchRatingsInt_6: 0 428 | switchRatingsInt_7: 0 429 | switchRatingsInt_8: 0 430 | switchRatingsInt_9: 0 431 | switchRatingsInt_10: 0 432 | switchRatingsInt_11: 0 433 | switchRatingsInt_12: 0 434 | switchLocalCommunicationIds_0: 435 | switchLocalCommunicationIds_1: 436 | switchLocalCommunicationIds_2: 437 | switchLocalCommunicationIds_3: 438 | switchLocalCommunicationIds_4: 439 | switchLocalCommunicationIds_5: 440 | switchLocalCommunicationIds_6: 441 | switchLocalCommunicationIds_7: 442 | switchParentalControl: 0 443 | switchAllowsScreenshot: 1 444 | switchAllowsVideoCapturing: 1 445 | switchAllowsRuntimeAddOnContentInstall: 0 446 | switchDataLossConfirmation: 0 447 | switchUserAccountLockEnabled: 0 448 | switchSystemResourceMemory: 16777216 449 | switchSupportedNpadStyles: 22 450 | switchNativeFsCacheSize: 32 451 | switchIsHoldTypeHorizontal: 0 452 | switchSupportedNpadCount: 8 453 | switchSocketConfigEnabled: 0 454 | switchTcpInitialSendBufferSize: 32 455 | switchTcpInitialReceiveBufferSize: 64 456 | switchTcpAutoSendBufferSizeMax: 256 457 | switchTcpAutoReceiveBufferSizeMax: 256 458 | switchUdpSendBufferSize: 9 459 | switchUdpReceiveBufferSize: 42 460 | switchSocketBufferEfficiency: 4 461 | switchSocketInitializeEnabled: 1 462 | switchNetworkInterfaceManagerInitializeEnabled: 1 463 | switchPlayerConnectionEnabled: 1 464 | switchUseNewStyleFilepaths: 0 465 | switchUseMicroSleepForYield: 1 466 | switchMicroSleepForYieldTime: 25 467 | ps4NPAgeRating: 12 468 | ps4NPTitleSecret: 469 | ps4NPTrophyPackPath: 470 | ps4ParentalLevel: 11 471 | ps4ContentID: ED1633-NPXX51362_00-0000000000000000 472 | ps4Category: 0 473 | ps4MasterVersion: 01.00 474 | ps4AppVersion: 01.00 475 | ps4AppType: 0 476 | ps4ParamSfxPath: 477 | ps4VideoOutPixelFormat: 0 478 | ps4VideoOutInitialWidth: 1920 479 | ps4VideoOutBaseModeInitialWidth: 1920 480 | ps4VideoOutReprojectionRate: 60 481 | ps4PronunciationXMLPath: 482 | ps4PronunciationSIGPath: 483 | ps4BackgroundImagePath: 484 | ps4StartupImagePath: 485 | ps4StartupImagesFolder: 486 | ps4IconImagesFolder: 487 | ps4SaveDataImagePath: 488 | ps4SdkOverride: 489 | ps4BGMPath: 490 | ps4ShareFilePath: 491 | ps4ShareOverlayImagePath: 492 | ps4PrivacyGuardImagePath: 493 | ps4ExtraSceSysFile: 494 | ps4NPtitleDatPath: 495 | ps4RemotePlayKeyAssignment: -1 496 | ps4RemotePlayKeyMappingDir: 497 | ps4PlayTogetherPlayerCount: 0 498 | ps4EnterButtonAssignment: 2 499 | ps4ApplicationParam1: 0 500 | ps4ApplicationParam2: 0 501 | ps4ApplicationParam3: 0 502 | ps4ApplicationParam4: 0 503 | ps4DownloadDataSize: 0 504 | ps4GarlicHeapSize: 2048 505 | ps4ProGarlicHeapSize: 2560 506 | playerPrefsMaxSize: 32768 507 | ps4Passcode: bi9UOuSpM2Tlh01vOzwvSikHFswuzleh 508 | ps4pnSessions: 1 509 | ps4pnPresence: 1 510 | ps4pnFriends: 1 511 | ps4pnGameCustomData: 1 512 | playerPrefsSupport: 0 513 | enableApplicationExit: 0 514 | resetTempFolder: 1 515 | restrictedAudioUsageRights: 0 516 | ps4UseResolutionFallback: 0 517 | ps4ReprojectionSupport: 0 518 | ps4UseAudio3dBackend: 0 519 | ps4UseLowGarlicFragmentationMode: 1 520 | ps4SocialScreenEnabled: 0 521 | ps4ScriptOptimizationLevel: 2 522 | ps4Audio3dVirtualSpeakerCount: 14 523 | ps4attribCpuUsage: 0 524 | ps4PatchPkgPath: 525 | ps4PatchLatestPkgPath: 526 | ps4PatchChangeinfoPath: 527 | ps4PatchDayOne: 0 528 | ps4attribUserManagement: 0 529 | ps4attribMoveSupport: 0 530 | ps4attrib3DSupport: 0 531 | ps4attribShareSupport: 0 532 | ps4attribExclusiveVR: 0 533 | ps4disableAutoHideSplash: 0 534 | ps4videoRecordingFeaturesUsed: 0 535 | ps4contentSearchFeaturesUsed: 0 536 | ps4CompatibilityPS5: 0 537 | ps4AllowPS5Detection: 0 538 | ps4GPU800MHz: 1 539 | ps4attribEyeToEyeDistanceSettingVR: 0 540 | ps4IncludedModules: [] 541 | ps4attribVROutputEnabled: 0 542 | monoEnv: 543 | splashScreenBackgroundSourceLandscape: {fileID: 0} 544 | splashScreenBackgroundSourcePortrait: {fileID: 0} 545 | blurSplashScreenBackground: 1 546 | spritePackerPolicy: 547 | webGLMemorySize: 32 548 | webGLExceptionSupport: 1 549 | webGLNameFilesAsHashes: 0 550 | webGLDataCaching: 1 551 | webGLDebugSymbols: 0 552 | webGLEmscriptenArgs: 553 | webGLModulesDirectory: 554 | webGLTemplate: APPLICATION:Default 555 | webGLAnalyzeBuildSize: 0 556 | webGLUseEmbeddedResources: 0 557 | webGLCompressionFormat: 0 558 | webGLWasmArithmeticExceptions: 0 559 | webGLLinkerTarget: 1 560 | webGLThreadsSupport: 0 561 | webGLDecompressionFallback: 0 562 | scriptingDefineSymbols: {} 563 | additionalCompilerArguments: {} 564 | platformArchitecture: {} 565 | scriptingBackend: {} 566 | il2cppCompilerConfiguration: {} 567 | managedStrippingLevel: {} 568 | incrementalIl2cppBuild: {} 569 | suppressCommonWarnings: 1 570 | allowUnsafeCode: 0 571 | useDeterministicCompilation: 1 572 | useReferenceAssemblies: 1 573 | enableRoslynAnalyzers: 1 574 | additionalIl2CppArgs: 575 | scriptingRuntimeVersion: 1 576 | gcIncremental: 1 577 | assemblyVersionValidation: 1 578 | gcWBarrierValidation: 0 579 | apiCompatibilityLevelPerPlatform: {} 580 | m_RenderingPath: 1 581 | m_MobileRenderingPath: 1 582 | metroPackageName: 2D_BuiltInRenderer 583 | metroPackageVersion: 584 | metroCertificatePath: 585 | metroCertificatePassword: 586 | metroCertificateSubject: 587 | metroCertificateIssuer: 588 | metroCertificateNotAfter: 0000000000000000 589 | metroApplicationDescription: 2D_BuiltInRenderer 590 | wsaImages: {} 591 | metroTileShortName: 592 | metroTileShowName: 0 593 | metroMediumTileShowName: 0 594 | metroLargeTileShowName: 0 595 | metroWideTileShowName: 0 596 | metroSupportStreamingInstall: 0 597 | metroLastRequiredScene: 0 598 | metroDefaultTileSize: 1 599 | metroTileForegroundText: 2 600 | metroTileBackgroundColor: {r: 0.13333334, g: 0.17254902, b: 0.21568628, a: 0} 601 | metroSplashScreenBackgroundColor: {r: 0.12941177, g: 0.17254902, b: 0.21568628, a: 1} 602 | metroSplashScreenUseBackgroundColor: 0 603 | platformCapabilities: {} 604 | metroTargetDeviceFamilies: {} 605 | metroFTAName: 606 | metroFTAFileTypes: [] 607 | metroProtocolName: 608 | XboxOneProductId: 609 | XboxOneUpdateKey: 610 | XboxOneSandboxId: 611 | XboxOneContentId: 612 | XboxOneTitleId: 613 | XboxOneSCId: 614 | XboxOneGameOsOverridePath: 615 | XboxOnePackagingOverridePath: 616 | XboxOneAppManifestOverridePath: 617 | XboxOneVersion: 1.0.0.0 618 | XboxOnePackageEncryption: 0 619 | XboxOnePackageUpdateGranularity: 2 620 | XboxOneDescription: 621 | XboxOneLanguage: 622 | - enus 623 | XboxOneCapability: [] 624 | XboxOneGameRating: {} 625 | XboxOneIsContentPackage: 0 626 | XboxOneEnhancedXboxCompatibilityMode: 0 627 | XboxOneEnableGPUVariability: 1 628 | XboxOneSockets: {} 629 | XboxOneSplashScreen: {fileID: 0} 630 | XboxOneAllowedProductIds: [] 631 | XboxOnePersistentLocalStorageSize: 0 632 | XboxOneXTitleMemory: 8 633 | XboxOneOverrideIdentityName: 634 | XboxOneOverrideIdentityPublisher: 635 | vrEditorSettings: {} 636 | cloudServicesEnabled: {} 637 | luminIcon: 638 | m_Name: 639 | m_ModelFolderPath: 640 | m_PortalFolderPath: 641 | luminCert: 642 | m_CertPath: 643 | m_SignPackage: 1 644 | luminIsChannelApp: 0 645 | luminVersion: 646 | m_VersionCode: 1 647 | m_VersionName: 648 | apiCompatibilityLevel: 6 649 | activeInputHandler: 0 650 | cloudProjectId: 651 | framebufferDepthMemorylessMode: 0 652 | qualitySettingsNames: [] 653 | projectName: 654 | organizationId: 655 | cloudEnabled: 0 656 | legacyClampBlendShapeWeights: 0 657 | virtualTexturingSupportEnabled: 0 658 | -------------------------------------------------------------------------------- /ProjectSettings/ProjectVersion.txt: -------------------------------------------------------------------------------- 1 | m_EditorVersion: 2020.3.24f1 2 | m_EditorVersionWithRevision: 2020.3.24f1 (79c78de19888) 3 | -------------------------------------------------------------------------------- /ProjectSettings/QualitySettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!47 &1 4 | QualitySettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 5 7 | m_CurrentQuality: 5 8 | m_QualitySettings: 9 | - serializedVersion: 2 10 | name: Very Low 11 | pixelLightCount: 0 12 | shadows: 0 13 | shadowResolution: 0 14 | shadowProjection: 1 15 | shadowCascades: 1 16 | shadowDistance: 15 17 | shadowNearPlaneOffset: 3 18 | shadowCascade2Split: 0.33333334 19 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 20 | shadowmaskMode: 0 21 | skinWeights: 1 22 | textureQuality: 1 23 | anisotropicTextures: 0 24 | antiAliasing: 0 25 | softParticles: 0 26 | softVegetation: 0 27 | realtimeReflectionProbes: 0 28 | billboardsFaceCameraPosition: 0 29 | vSyncCount: 0 30 | lodBias: 0.3 31 | maximumLODLevel: 0 32 | streamingMipmapsActive: 0 33 | streamingMipmapsAddAllCameras: 1 34 | streamingMipmapsMemoryBudget: 512 35 | streamingMipmapsRenderersPerFrame: 512 36 | streamingMipmapsMaxLevelReduction: 2 37 | streamingMipmapsMaxFileIORequests: 1024 38 | particleRaycastBudget: 4 39 | asyncUploadTimeSlice: 2 40 | asyncUploadBufferSize: 16 41 | asyncUploadPersistentBuffer: 1 42 | resolutionScalingFixedDPIFactor: 1 43 | customRenderPipeline: {fileID: 0} 44 | excludedTargetPlatforms: [] 45 | - serializedVersion: 2 46 | name: Low 47 | pixelLightCount: 0 48 | shadows: 0 49 | shadowResolution: 0 50 | shadowProjection: 1 51 | shadowCascades: 1 52 | shadowDistance: 20 53 | shadowNearPlaneOffset: 3 54 | shadowCascade2Split: 0.33333334 55 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 56 | shadowmaskMode: 0 57 | skinWeights: 2 58 | textureQuality: 0 59 | anisotropicTextures: 0 60 | antiAliasing: 0 61 | softParticles: 0 62 | softVegetation: 0 63 | realtimeReflectionProbes: 0 64 | billboardsFaceCameraPosition: 0 65 | vSyncCount: 0 66 | lodBias: 0.4 67 | maximumLODLevel: 0 68 | streamingMipmapsActive: 0 69 | streamingMipmapsAddAllCameras: 1 70 | streamingMipmapsMemoryBudget: 512 71 | streamingMipmapsRenderersPerFrame: 512 72 | streamingMipmapsMaxLevelReduction: 2 73 | streamingMipmapsMaxFileIORequests: 1024 74 | particleRaycastBudget: 16 75 | asyncUploadTimeSlice: 2 76 | asyncUploadBufferSize: 16 77 | asyncUploadPersistentBuffer: 1 78 | resolutionScalingFixedDPIFactor: 1 79 | customRenderPipeline: {fileID: 0} 80 | excludedTargetPlatforms: [] 81 | - serializedVersion: 2 82 | name: Medium 83 | pixelLightCount: 1 84 | shadows: 1 85 | shadowResolution: 0 86 | shadowProjection: 1 87 | shadowCascades: 1 88 | shadowDistance: 20 89 | shadowNearPlaneOffset: 3 90 | shadowCascade2Split: 0.33333334 91 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 92 | shadowmaskMode: 0 93 | skinWeights: 2 94 | textureQuality: 0 95 | anisotropicTextures: 1 96 | antiAliasing: 0 97 | softParticles: 0 98 | softVegetation: 0 99 | realtimeReflectionProbes: 0 100 | billboardsFaceCameraPosition: 0 101 | vSyncCount: 1 102 | lodBias: 0.7 103 | maximumLODLevel: 0 104 | streamingMipmapsActive: 0 105 | streamingMipmapsAddAllCameras: 1 106 | streamingMipmapsMemoryBudget: 512 107 | streamingMipmapsRenderersPerFrame: 512 108 | streamingMipmapsMaxLevelReduction: 2 109 | streamingMipmapsMaxFileIORequests: 1024 110 | particleRaycastBudget: 64 111 | asyncUploadTimeSlice: 2 112 | asyncUploadBufferSize: 16 113 | asyncUploadPersistentBuffer: 1 114 | resolutionScalingFixedDPIFactor: 1 115 | customRenderPipeline: {fileID: 0} 116 | excludedTargetPlatforms: [] 117 | - serializedVersion: 2 118 | name: High 119 | pixelLightCount: 2 120 | shadows: 2 121 | shadowResolution: 1 122 | shadowProjection: 1 123 | shadowCascades: 2 124 | shadowDistance: 40 125 | shadowNearPlaneOffset: 3 126 | shadowCascade2Split: 0.33333334 127 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 128 | shadowmaskMode: 1 129 | skinWeights: 2 130 | textureQuality: 0 131 | anisotropicTextures: 1 132 | antiAliasing: 0 133 | softParticles: 0 134 | softVegetation: 1 135 | realtimeReflectionProbes: 1 136 | billboardsFaceCameraPosition: 1 137 | vSyncCount: 1 138 | lodBias: 1 139 | maximumLODLevel: 0 140 | streamingMipmapsActive: 0 141 | streamingMipmapsAddAllCameras: 1 142 | streamingMipmapsMemoryBudget: 512 143 | streamingMipmapsRenderersPerFrame: 512 144 | streamingMipmapsMaxLevelReduction: 2 145 | streamingMipmapsMaxFileIORequests: 1024 146 | particleRaycastBudget: 256 147 | asyncUploadTimeSlice: 2 148 | asyncUploadBufferSize: 16 149 | asyncUploadPersistentBuffer: 1 150 | resolutionScalingFixedDPIFactor: 1 151 | customRenderPipeline: {fileID: 0} 152 | excludedTargetPlatforms: [] 153 | - serializedVersion: 2 154 | name: Very High 155 | pixelLightCount: 3 156 | shadows: 2 157 | shadowResolution: 2 158 | shadowProjection: 1 159 | shadowCascades: 2 160 | shadowDistance: 70 161 | shadowNearPlaneOffset: 3 162 | shadowCascade2Split: 0.33333334 163 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 164 | shadowmaskMode: 1 165 | skinWeights: 4 166 | textureQuality: 0 167 | anisotropicTextures: 2 168 | antiAliasing: 2 169 | softParticles: 1 170 | softVegetation: 1 171 | realtimeReflectionProbes: 1 172 | billboardsFaceCameraPosition: 1 173 | vSyncCount: 1 174 | lodBias: 1.5 175 | maximumLODLevel: 0 176 | streamingMipmapsActive: 0 177 | streamingMipmapsAddAllCameras: 1 178 | streamingMipmapsMemoryBudget: 512 179 | streamingMipmapsRenderersPerFrame: 512 180 | streamingMipmapsMaxLevelReduction: 2 181 | streamingMipmapsMaxFileIORequests: 1024 182 | particleRaycastBudget: 1024 183 | asyncUploadTimeSlice: 2 184 | asyncUploadBufferSize: 16 185 | asyncUploadPersistentBuffer: 1 186 | resolutionScalingFixedDPIFactor: 1 187 | customRenderPipeline: {fileID: 0} 188 | excludedTargetPlatforms: [] 189 | - serializedVersion: 2 190 | name: Ultra 191 | pixelLightCount: 4 192 | shadows: 2 193 | shadowResolution: 2 194 | shadowProjection: 1 195 | shadowCascades: 4 196 | shadowDistance: 150 197 | shadowNearPlaneOffset: 3 198 | shadowCascade2Split: 0.33333334 199 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 200 | shadowmaskMode: 1 201 | skinWeights: 255 202 | textureQuality: 0 203 | anisotropicTextures: 2 204 | antiAliasing: 2 205 | softParticles: 1 206 | softVegetation: 1 207 | realtimeReflectionProbes: 1 208 | billboardsFaceCameraPosition: 1 209 | vSyncCount: 1 210 | lodBias: 2 211 | maximumLODLevel: 0 212 | streamingMipmapsActive: 0 213 | streamingMipmapsAddAllCameras: 1 214 | streamingMipmapsMemoryBudget: 512 215 | streamingMipmapsRenderersPerFrame: 512 216 | streamingMipmapsMaxLevelReduction: 2 217 | streamingMipmapsMaxFileIORequests: 1024 218 | particleRaycastBudget: 4096 219 | asyncUploadTimeSlice: 2 220 | asyncUploadBufferSize: 16 221 | asyncUploadPersistentBuffer: 1 222 | resolutionScalingFixedDPIFactor: 1 223 | customRenderPipeline: {fileID: 0} 224 | excludedTargetPlatforms: [] 225 | m_PerPlatformDefaultQuality: 226 | Android: 2 227 | Lumin: 5 228 | Nintendo Switch: 5 229 | PS4: 5 230 | Stadia: 5 231 | Standalone: 5 232 | WebGL: 3 233 | Windows Store Apps: 5 234 | XboxOne: 5 235 | iPhone: 2 236 | tvOS: 2 237 | -------------------------------------------------------------------------------- /ProjectSettings/TagManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!78 &1 4 | TagManager: 5 | serializedVersion: 2 6 | tags: [] 7 | layers: 8 | - Default 9 | - TransparentFX 10 | - Ignore Raycast 11 | - 12 | - Water 13 | - UI 14 | - 15 | - 16 | - 17 | - 18 | - 19 | - 20 | - 21 | - 22 | - 23 | - 24 | - 25 | - 26 | - 27 | - 28 | - 29 | - 30 | - 31 | - 32 | - 33 | - 34 | - 35 | - 36 | - 37 | - 38 | - 39 | - 40 | m_SortingLayers: 41 | - name: Default 42 | uniqueID: 0 43 | locked: 0 44 | -------------------------------------------------------------------------------- /ProjectSettings/TimeManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!5 &1 4 | TimeManager: 5 | m_ObjectHideFlags: 0 6 | Fixed Timestep: 0.02 7 | Maximum Allowed Timestep: 0.33333334 8 | m_TimeScale: 1 9 | Maximum Particle Timestep: 0.03 10 | -------------------------------------------------------------------------------- /ProjectSettings/UnityConnectSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!310 &1 4 | UnityConnectSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 1 7 | m_Enabled: 0 8 | m_TestMode: 0 9 | m_EventOldUrl: https://api.uca.cloud.unity3d.com/v1/events 10 | m_EventUrl: https://cdp.cloud.unity3d.com/v1/events 11 | m_ConfigUrl: https://config.uca.cloud.unity3d.com 12 | m_DashboardUrl: https://dashboard.unity3d.com 13 | m_TestInitMode: 0 14 | CrashReportingSettings: 15 | m_EventUrl: https://perf-events.cloud.unity3d.com 16 | m_Enabled: 0 17 | m_LogBufferSize: 10 18 | m_CaptureEditorExceptions: 1 19 | UnityPurchasingSettings: 20 | m_Enabled: 0 21 | m_TestMode: 0 22 | UnityAnalyticsSettings: 23 | m_Enabled: 0 24 | m_TestMode: 0 25 | m_InitializeOnStartup: 1 26 | UnityAdsSettings: 27 | m_Enabled: 0 28 | m_InitializeOnStartup: 1 29 | m_TestMode: 0 30 | m_IosGameId: 31 | m_AndroidGameId: 32 | m_GameIds: {} 33 | m_GameId: 34 | PerformanceReportingSettings: 35 | m_Enabled: 0 36 | -------------------------------------------------------------------------------- /ProjectSettings/VFXManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!937362698 &1 4 | VFXManager: 5 | m_ObjectHideFlags: 0 6 | m_IndirectShader: {fileID: 0} 7 | m_CopyBufferShader: {fileID: 0} 8 | m_SortShader: {fileID: 0} 9 | m_StripUpdateShader: {fileID: 0} 10 | m_RenderPipeSettingsPath: 11 | m_FixedTimeStep: 0.016666668 12 | m_MaxDeltaTime: 0.05 13 | -------------------------------------------------------------------------------- /ProjectSettings/VersionControlSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!890905787 &1 4 | VersionControlSettings: 5 | m_ObjectHideFlags: 0 6 | m_Mode: Visible Meta Files 7 | m_CollabEditorSettings: 8 | inProgressEnabled: 1 9 | -------------------------------------------------------------------------------- /ProjectSettings/XRSettings.asset: -------------------------------------------------------------------------------- 1 | { 2 | "m_SettingKeys": [ 3 | "VR Device Disabled", 4 | "VR Device User Alert" 5 | ], 6 | "m_SettingValues": [ 7 | "False", 8 | "False" 9 | ] 10 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Textures Hunter Unity3D Tool ![unity](https://img.shields.io/badge/Unity-100000?style=for-the-badge&logo=unity&logoColor=white) 2 | 3 | ![stability-stable](https://img.shields.io/badge/stability-stable-green.svg) 4 | [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) 5 | [![Maintenance](https://img.shields.io/badge/Maintained%3F-yes-green.svg)](https://GitHub.com/Naereen/StrapDown.js/graphs/commit-activity) 6 | 7 | ## 8 | This tool provides summary of all textures in Unity project. 9 | 10 | It performs an analysis of atlas and non-atlas textures to give some recommendations upon their compression settings: 11 | e.g. detect issues like 12 | - Only POT textures can be compressed to PVRTC format 13 | - Only textures with width/height being multiple of 4 can be compressed to Crunch format 14 | - etc 15 | 16 | It also helps to analyze all your atlases at once and highlights issues like 17 | - if their textures used in Resources and/or Addressables (which may lead to duplicated textures in build) 18 | - if there are some ambiguous settings between atlases 19 | - etc 20 | 21 | You can set recommended compression settings and it will mark textures and atlases that do not use them. 22 | 23 | All code combined into one script for easier portability. 24 | So you can just copy-paste [TextureHunter.cs](./Packages/TextureHunter/Editor/TextureHunter.cs) to your project in any Editor folder. 25 | 26 | Use "Tools/Texture Hunter" menu to launch it. 27 | 28 | ##### Textures View 29 | 30 | ![plot](./Screenshots/textures_screen.png) 31 | 32 | ##### Atlases View 33 | 34 | ![plot](./Screenshots/atlases_screen.png) 35 | 36 | ## Installation 37 | 38 | 1. Just copy and paste file [TextureHunter.cs](./Packages/TextureHunter/Editor/TextureHunter.cs) inside Editor folder 39 | 2. [WIP] via Unity's Package Manager 40 | 41 | ## Contributions 42 | 43 | Feel free to [report bugs, request new features](https://github.com/AlexeyPerov/Unity-Texture-Hunter/issues) 44 | or to [contribute](https://github.com/AlexeyPerov/Unity-Texture-Hunter/pulls) to this project! 45 | 46 | ## Other tools 47 | 48 | ##### Dependencies Hunter 49 | 50 | - To find unreferenced assets in Unity project see [Dependencies-Hunter](https://github.com/AlexeyPerov/Unity-Dependencies-Hunter). 51 | 52 | ##### Missing References Hunter 53 | 54 | - To find missing or empty references in your assets see [Missing-References-Hunter](https://github.com/AlexeyPerov/Unity-MissingReferences-Hunter). 55 | 56 | ##### Editor Coroutines 57 | 58 | - Unity Editor Coroutines alternative version [Lite-Editor-Coroutines](https://github.com/AlexeyPerov/Unity-Lite-Editor-Coroutines). 59 | - Simplified and compact version [Pocket-Editor-Coroutines](https://github.com/AlexeyPerov/Unity-Pocket-Editor-Coroutines). -------------------------------------------------------------------------------- /Screenshots/atlases_screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexeyPerov/Unity-Textures-Hunter/c746c012a53970b94416cd88cff8d58eba4178c1/Screenshots/atlases_screen.png -------------------------------------------------------------------------------- /Screenshots/textures_screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexeyPerov/Unity-Textures-Hunter/c746c012a53970b94416cd88cff8d58eba4178c1/Screenshots/textures_screen.png -------------------------------------------------------------------------------- /UserSettings/EditorUserSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!162 &1 4 | EditorUserSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 4 7 | m_ConfigSettings: 8 | RecentlyUsedScenePath-0: 9 | value: 22424703114646680e0b0227036c6c111b07142f1f2b233e2867083debf42d 10 | flags: 0 11 | RecentlyUsedScenePath-1: 12 | value: 224247031146466f081d181113265115580216233831 13 | flags: 0 14 | vcSharedLogLevel: 15 | value: 0d5e400f0650 16 | flags: 0 17 | m_VCAutomaticAdd: 1 18 | m_VCDebugCom: 0 19 | m_VCDebugCmd: 0 20 | m_VCDebugOut: 0 21 | m_SemanticMergeMode: 2 22 | m_VCShowFailedCheckout: 1 23 | m_VCOverwriteFailedCheckoutAssets: 1 24 | m_VCProjectOverlayIcons: 1 25 | m_VCHierarchyOverlayIcons: 1 26 | m_VCOtherOverlayIcons: 1 27 | m_VCAllowAsyncUpdate: 1 28 | --------------------------------------------------------------------------------