├── .gitattributes ├── .gitignore ├── Assets └── Trisibo │ └── Delayed asset │ ├── DelayedAsset.cs │ ├── DelayedAssetProxy.cs │ ├── DelayedAssetTypeAttribute.cs │ ├── Editor │ ├── DelayedAssetDrawer.cs │ └── DelayedAssetProxyEditor.cs │ ├── LICENSE.txt │ └── Readme.txt ├── Delayed asset.unitypackage ├── LICENSE └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Visual Studio 2015 cache/options directory 2 | /.vs/ 3 | 4 | # Autogenerated VS/MD solution and project files 5 | /*.csproj 6 | /*.unityproj 7 | /*.sln 8 | /*.suo 9 | /*.tmp 10 | /*.user 11 | /*.userprefs 12 | /*.pidb 13 | /*.booproj 14 | /*.svd 15 | 16 | # OS generated 17 | *.DS_[Ss]tore 18 | *.DS_[Ss]tore? 19 | *.Spotlight-V100 20 | *.[Tt]rashes 21 | [Ee]hthumbs.db 22 | [Tt]humbs.db 23 | *.pidb.meta 24 | [Tt]humbs.db.meta 25 | sysinfo.txt 26 | 27 | # Usually unneeded Unity stuff 28 | /[Ll]ibrary/ 29 | /[Tt]emp/ 30 | /[Oo]bj/ 31 | /[Ee]xported[Oo]bj/ 32 | 33 | # Unity stuff not needed for this repository 34 | /ProjectSettings/ 35 | *.meta 36 | /[Aa]ssets/[Tt]est/ 37 | /UnityPackageManager 38 | /Logs/ 39 | /Packages/ 40 | 41 | # Test builds 42 | /Builds/ 43 | -------------------------------------------------------------------------------- /Assets/Trisibo/Delayed asset/DelayedAsset.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2017 Trinidad Sibajas Bodoque 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | 22 | using UnityEngine; 23 | using System; 24 | #if UNITY_EDITOR 25 | using UnityEditor; 26 | #endif 27 | 28 | namespace Trisibo 29 | { 30 | /// 31 | /// Use on a serialized field of another MonoBehaviour object to allow loading an asset on demand, 32 | /// instead of when the container object is loaded. 33 | /// 34 | 35 | [Serializable] 36 | public class DelayedAsset 37 | #if UNITY_EDITOR 38 | : ISerializationCallbackReceiver 39 | #endif 40 | { 41 | #region Serialized data 42 | 43 | 44 | // The asset, only available on the editor to be able to set it from the inspector: 45 | #if UNITY_EDITOR 46 | [SerializeField, HideInInspector] UnityEngine.Object asset = null; 47 | #endif 48 | 49 | 50 | // The data needed to load the asset: 51 | [SerializeField, HideInInspector] string assetRelativePath = null; 52 | [SerializeField, HideInInspector] string assetTypeString = null; 53 | 54 | 55 | #endregion 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | #region Overloaded operators 65 | 66 | 67 | /// 68 | /// "==" operator. 69 | /// 70 | 71 | public static bool operator ==(DelayedAsset a, DelayedAsset b) 72 | { 73 | if (ReferenceEquals(a, null)) 74 | return ReferenceEquals(b, null) || string.IsNullOrEmpty(b.assetRelativePath); 75 | 76 | if (ReferenceEquals(b, null)) 77 | return ReferenceEquals(a, null) || string.IsNullOrEmpty(a.assetRelativePath); 78 | 79 | if (a.Equals(b)) 80 | return true; 81 | 82 | if (string.IsNullOrEmpty(a.assetRelativePath)) 83 | return string.IsNullOrEmpty(b.assetRelativePath); 84 | 85 | return a.assetRelativePath.Equals(b.assetRelativePath, StringComparison.InvariantCulture) && a.AssetType == b.AssetType; 86 | } 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | /// 96 | /// "!=" operator. 97 | /// 98 | 99 | public static bool operator !=(DelayedAsset a, DelayedAsset b) 100 | { 101 | return !(a == b); 102 | } 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | /// 112 | /// Inplicit bool operator. 113 | /// 114 | 115 | public static implicit operator bool(DelayedAsset a) 116 | { 117 | return !(a == null); 118 | } 119 | 120 | 121 | #endregion 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | #region Object methods overrides 131 | 132 | 133 | /// 134 | /// Implementation of . 135 | /// 136 | 137 | public override bool Equals(object obj) 138 | { 139 | return base.Equals(obj); 140 | } 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | /// 150 | /// Implementation of . 151 | /// 152 | 153 | public override int GetHashCode() 154 | { 155 | return base.GetHashCode(); 156 | } 157 | 158 | 159 | #endregion 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | #region Runtime data 169 | 170 | 171 | // The asset type: 172 | Type _assetType; 173 | Type AssetType 174 | { 175 | get { return _assetType ?? (_assetType = string.IsNullOrEmpty(assetTypeString) ? null : Type.GetType(assetTypeString)); } 176 | } 177 | 178 | 179 | // The asset once loaded at runtime: 180 | UnityEngine.Object _loadedAsset; 181 | 182 | UnityEngine.Object LoadedAsset 183 | { 184 | get 185 | { 186 | if (_loadedAsset == null && asyncLoadedAssetGetter != null) 187 | _loadedAsset = asyncLoadedAssetGetter(); 188 | return _loadedAsset; 189 | } 190 | 191 | set 192 | { 193 | _loadedAsset = value; 194 | } 195 | } 196 | 197 | 198 | // The async load request, if any: 199 | AsyncLoadRequest asyncLoadRequest; 200 | Func asyncLoadedAssetGetter; 201 | 202 | 203 | #endregion 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | #region Data types 213 | 214 | 215 | /// 216 | /// Represents an async request to load the original asset. 217 | /// Behaves in a similar way to Unity's . 218 | /// 219 | 220 | public class AsyncLoadRequest : CustomYieldInstruction 221 | { 222 | // The original resource request. Can be null if no resource request was done: 223 | readonly ResourceRequest resourceRequest; 224 | 225 | 226 | // The already loaded asset if there was no resource request, null otherwise: 227 | readonly UnityEngine.Object assetIfNoResourceRequest; 228 | 229 | 230 | 231 | 232 | /// 233 | /// Constructor. 234 | /// 235 | /// The resource request used to load the asset. Cannot be null; if no resource request was done, use the constructor that accepts an already loaded asset. 236 | /// Receives a method that returns the loaded asset (not the original asset). 237 | 238 | public AsyncLoadRequest(ResourceRequest resourceRequest, out Func actualLoadedAssetGetter) 239 | { 240 | this.resourceRequest = resourceRequest; 241 | actualLoadedAssetGetter = GetActualLoadedAsset; 242 | } 243 | 244 | 245 | 246 | 247 | /// 248 | /// Constructor. 249 | /// 250 | /// This must contain an already loaded asset. Use this constructor only if there was no resource request done. 251 | /// Receives a method that returns the loaded asset (not the original asset). 252 | 253 | public AsyncLoadRequest(UnityEngine.Object alreadyLoadedAsset, out Func actualLoadedAssetGetter) 254 | { 255 | assetIfNoResourceRequest = alreadyLoadedAsset; 256 | actualLoadedAssetGetter = GetActualLoadedAsset; 257 | } 258 | 259 | 260 | 261 | 262 | /// 263 | /// Has the asset loading finished? 264 | /// See documentation for more details. 265 | /// 266 | 267 | public bool IsDone 268 | { 269 | get 270 | { 271 | return resourceRequest != null ? resourceRequest.isDone : true; 272 | } 273 | } 274 | 275 | 276 | 277 | 278 | /// 279 | /// Allows tweaking the order in which async operations will be performed. 280 | /// See documentation for more details. 281 | /// If no actual loading was necessary, assigning a value will have no effect, and will always return -1. 282 | /// 283 | 284 | public int Priority 285 | { 286 | get 287 | { 288 | return resourceRequest != null ? resourceRequest.priority : -1; 289 | } 290 | 291 | set 292 | { 293 | if (resourceRequest != null) 294 | resourceRequest.priority = value; 295 | } 296 | } 297 | 298 | 299 | 300 | 301 | /// 302 | /// The progress of the operation. 303 | /// See documentation for more details. 304 | /// 305 | 306 | public float Progress 307 | { 308 | get 309 | { 310 | return resourceRequest != null ? resourceRequest.progress : 1; 311 | } 312 | } 313 | 314 | 315 | 316 | 317 | /// 318 | /// Asset object being loaded. 319 | /// See documentation for more details. The difference is that trying to get the value before is true won't stall the loading process, but will cause an . 320 | /// 321 | /// Thrown if is false when trying to access the asset. 322 | 323 | public UnityEngine.Object Asset 324 | { 325 | get 326 | { 327 | if (!IsDone) 328 | throw new InvalidOperationException("Tried to access the asset when IsDone was false"); 329 | 330 | return GetOriginalAsset(GetActualLoadedAsset()); 331 | } 332 | } 333 | 334 | 335 | 336 | 337 | /// 338 | /// implementation. 339 | /// 340 | 341 | public override bool keepWaiting 342 | { 343 | get 344 | { 345 | return !IsDone; 346 | } 347 | } 348 | 349 | 350 | 351 | 352 | /// 353 | /// Returns the loaded asset (which will be different to the original asset in case the loaded asset is a ). 354 | /// Will return null if is false. 355 | /// 356 | /// The loaded asset. 357 | 358 | UnityEngine.Object GetActualLoadedAsset() 359 | { 360 | if (IsDone) 361 | return resourceRequest != null ? resourceRequest.asset : assetIfNoResourceRequest; 362 | else 363 | return null; 364 | } 365 | } 366 | 367 | 368 | #endregion 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | #region Asset loading methods 378 | 379 | 380 | /// 381 | /// Loads the original asset. Does not attempt to load it again if it was already loaded. 382 | /// To unload it do not use , use instead. 383 | /// 384 | /// The loaded asset, or null if it wasn't found or hadn't been assigned. 385 | 386 | public UnityEngine.Object Load() 387 | { 388 | #if UNITY_EDITOR 389 | { 390 | UpdateRuntimeSerializedData(); 391 | } 392 | #endif 393 | 394 | 395 | if (LoadedAsset == null && !string.IsNullOrEmpty(assetRelativePath)) 396 | { 397 | LoadedAsset = Resources.Load(assetRelativePath, AssetType); 398 | } 399 | 400 | return GetOriginalAsset(LoadedAsset); 401 | } 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | /// 411 | /// Asynchronously loads the original asset. Does not attempt to load it again if it was already loaded. 412 | /// To unload it do not use , use instead. 413 | /// 414 | /// An object, from which the asset can be retrieved once the operation is completed. Will be null if the original asset couldn't be found, or hadn't been assigned. 415 | 416 | public AsyncLoadRequest LoadAsync() 417 | { 418 | #if UNITY_EDITOR 419 | { 420 | UpdateRuntimeSerializedData(); 421 | } 422 | #endif 423 | 424 | 425 | if (asyncLoadRequest == null) 426 | { 427 | if (LoadedAsset != null) 428 | { 429 | asyncLoadRequest = new AsyncLoadRequest(LoadedAsset, out asyncLoadedAssetGetter); 430 | } 431 | else if (!string.IsNullOrEmpty(assetRelativePath)) 432 | { 433 | ResourceRequest resourceRequest = Resources.LoadAsync(assetRelativePath, AssetType); 434 | asyncLoadRequest = new AsyncLoadRequest(resourceRequest, out asyncLoadedAssetGetter); 435 | } 436 | } 437 | 438 | return asyncLoadRequest; 439 | } 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | /// 449 | /// Returns the original asset from the specified loaded asset, checking if the loaded asset is a instance. 450 | /// 451 | /// The loaded asset. 452 | /// The original asset. 453 | 454 | static UnityEngine.Object GetOriginalAsset(UnityEngine.Object loadedAsset) 455 | { 456 | return (loadedAsset is DelayedAssetProxy) ? ((DelayedAssetProxy)loadedAsset).Asset : loadedAsset; 457 | } 458 | 459 | 460 | #endregion 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | #region Asset unloading methods 470 | 471 | 472 | /// 473 | /// Unloads the original asset if it's currently loaded. 474 | /// Must not be called if there's an unfinished operation (generated from a previous call to ). 475 | /// 476 | /// If the original asset is of a type that cannot be directly unloaded by Unity (, , or ), force a call to instead. Use it with care, since it may be slow. 477 | /// Thrown if there's an unfinished operation when this method is called. 478 | 479 | public void Unload(bool forceUnloadAllUnusedAssetsIfAssetNotUnloadable = false) 480 | { 481 | if (asyncLoadRequest != null && !asyncLoadRequest.IsDone) 482 | throw new InvalidOperationException("Called DelayedAsset.Unload() when there was an AsyncLoadRequest operation in progress"); 483 | 484 | 485 | if (LoadedAsset != null) 486 | { 487 | // If the original asset is inside a proxy, unload it. Only if not in the editor, since otherwise it won't allow to load the asset again: 488 | #if !UNITY_EDITOR 489 | { 490 | var originalAsset = GetOriginalAsset(LoadedAsset); 491 | if (originalAsset != null && originalAsset != LoadedAsset) 492 | { 493 | if (CanBeDirectlyUnloaded(originalAsset)) 494 | { 495 | Resources.UnloadAsset(originalAsset); 496 | } 497 | else if (forceUnloadAllUnusedAssetsIfAssetNotUnloadable) 498 | { 499 | originalAsset = null; 500 | Resources.UnloadUnusedAssets(); 501 | } 502 | } 503 | } 504 | #endif 505 | 506 | 507 | // Unload the loaded asset: 508 | if (CanBeDirectlyUnloaded(LoadedAsset)) 509 | { 510 | Resources.UnloadAsset(LoadedAsset); 511 | } 512 | else if (forceUnloadAllUnusedAssetsIfAssetNotUnloadable) 513 | { 514 | LoadedAsset = null; 515 | Resources.UnloadUnusedAssets(); 516 | } 517 | } 518 | 519 | LoadedAsset = null; 520 | asyncLoadRequest = null; 521 | asyncLoadedAssetGetter = null; 522 | } 523 | 524 | 525 | 526 | 527 | 528 | 529 | 530 | 531 | /// 532 | /// Checks whether the specified asset can be directly unloaded with . 533 | /// Some assets can't (, , and ). 534 | /// 535 | /// The asset to check. 536 | /// Whether the specified asset can be directly unloaded with . 537 | 538 | static bool CanBeDirectlyUnloaded(UnityEngine.Object asset) 539 | { 540 | Type assetType = asset.GetType(); 541 | return !typeof(Component).IsAssignableFrom(assetType) && !typeof(GameObject).IsAssignableFrom(assetType) && !typeof(AssetBundle).IsAssignableFrom(assetType); 542 | } 543 | 544 | 545 | #endregion 546 | 547 | 548 | 549 | 550 | 551 | 552 | 553 | 554 | #region ISerializationCallbackReceiver implementation 555 | #if UNITY_EDITOR 556 | 557 | 558 | /// 559 | /// implementation. 560 | /// 561 | 562 | void ISerializationCallbackReceiver.OnBeforeSerialize() 563 | { 564 | UpdateRuntimeSerializedData(); 565 | } 566 | 567 | 568 | 569 | 570 | 571 | 572 | 573 | 574 | /// 575 | /// implementation. 576 | /// 577 | 578 | void ISerializationCallbackReceiver.OnAfterDeserialize() 579 | { 580 | LoadedAsset = null; 581 | _assetType = null; 582 | asyncLoadRequest = null; 583 | asyncLoadedAssetGetter = null; 584 | } 585 | 586 | 587 | #endif 588 | #endregion 589 | 590 | 591 | 592 | 593 | 594 | 595 | 596 | 597 | #region Editor members 598 | #if UNITY_EDITOR 599 | 600 | 601 | /// 602 | /// Only in the editor. 603 | /// The original asset object. 604 | /// 605 | 606 | public UnityEngine.Object Editor_OriginalAsset 607 | { 608 | get 609 | { 610 | return asset; 611 | } 612 | } 613 | 614 | 615 | 616 | 617 | 618 | 619 | 620 | 621 | /// 622 | /// Only in editor. 623 | /// Updates the serialized data used at runtime, using the current assigned asset. 624 | /// 625 | 626 | void UpdateRuntimeSerializedData() 627 | { 628 | assetRelativePath = null; 629 | assetTypeString = null; 630 | 631 | if ((object)asset != null && asset.GetInstanceID() != 0) //-> We cast to object because in some situations the asset instance may be some kind of "special" one that Unity considers null. 632 | { 633 | string assetAbsolutePath = AssetDatabase.GetAssetPath(asset.GetInstanceID()); 634 | assetRelativePath = GetResourcesRelativeAssetPath(assetAbsolutePath); 635 | 636 | string error = CheckForErrors(asset, assetRelativePath); 637 | if (error != null) 638 | { 639 | assetRelativePath = null; 640 | assetTypeString = null; 641 | Debug.LogError("Delayed asset error: " + error); 642 | } 643 | else 644 | { 645 | assetTypeString = asset.GetType().AssemblyQualifiedName; 646 | } 647 | } 648 | } 649 | 650 | 651 | 652 | 653 | 654 | 655 | 656 | 657 | /// 658 | /// Only in the editor. 659 | /// Retrieves the asset path relative to a resources folder. 660 | /// 661 | /// The absolute path of the asset. 662 | /// The path relative to a resources folder, null if the asset is not inside a resources folder, either directly or inside a subfolder in the hierarchy. 663 | 664 | public static string GetResourcesRelativeAssetPath(string assetAbsolutePath) 665 | { 666 | const string resourcesPathString = "/Resources/"; 667 | 668 | int resourcesStringIndex = assetAbsolutePath.IndexOf(resourcesPathString); 669 | if (resourcesStringIndex == -1) 670 | { 671 | return null; 672 | } 673 | 674 | int start = resourcesStringIndex + resourcesPathString.Length; 675 | int dot = assetAbsolutePath.LastIndexOf('.'); 676 | return assetAbsolutePath.Substring(start, (dot >= 0 ? dot : assetAbsolutePath.Length) - start); 677 | } 678 | 679 | 680 | 681 | 682 | 683 | 684 | 685 | 686 | /// 687 | /// Only in the editor. 688 | /// Searches for any asset with the same path relative to a resources folder and the same type as the supplied asset. 689 | /// 690 | /// The asset. 691 | /// The path relative to a resources folder. 692 | /// One of the assets found, null if none. 693 | 694 | public static UnityEngine.Object FindAssetWithSameTypeAndRelativePath(UnityEngine.Object asset, string resourcesRelativePath) 695 | { 696 | int assetId = asset.GetInstanceID(); 697 | 698 | UnityEngine.Object[] allAssets = Resources.LoadAll(resourcesRelativePath, asset.GetType()); 699 | for (int i = 0; i < allAssets.Length; i++) 700 | { 701 | if (allAssets[i].GetInstanceID() != assetId) 702 | return allAssets[i]; 703 | } 704 | 705 | return null; 706 | } 707 | 708 | 709 | 710 | 711 | 712 | 713 | 714 | 715 | /// 716 | /// Only in the editor. 717 | /// Checks for errors in an assigned asset. 718 | /// 719 | /// The asset. 720 | /// The path relative to a resources folder, if any. 721 | /// The error text for the first error found, null if there were no errors. 722 | 723 | 724 | public static string CheckForErrors(UnityEngine.Object asset, string resourcesRelativePath) 725 | { 726 | string error = null; 727 | 728 | if (string.IsNullOrEmpty(resourcesRelativePath)) 729 | { 730 | error = "The asset \"" + AssetDatabase.GetAssetPath(asset.GetInstanceID()) + "\" is not inside a \"Resources\" folder."; 731 | } 732 | else 733 | { 734 | UnityEngine.Object otherAsset = FindAssetWithSameTypeAndRelativePath(asset, resourcesRelativePath); 735 | if (otherAsset != null) 736 | { 737 | error = "The asset \"" + AssetDatabase.GetAssetPath(asset.GetInstanceID()) + "\" doesn't have a unique type and path relative to a \"Resources\" folder, this other asset has the same ones: \"" + AssetDatabase.GetAssetPath(otherAsset) + "\"."; 738 | } 739 | } 740 | 741 | return error; 742 | } 743 | 744 | 745 | #endif 746 | #endregion 747 | } 748 | } 749 | -------------------------------------------------------------------------------- /Assets/Trisibo/Delayed asset/DelayedAssetProxy.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2017 Trinidad Sibajas Bodoque 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | 22 | using UnityEngine; 23 | 24 | namespace Trisibo 25 | { 26 | /// 27 | /// Makes it possible to use assets from any folder on a , 28 | /// assigning the original asset to the , which must be inside a "Resources" folder. 29 | /// 30 | 31 | [CreateAssetMenu(menuName = "Trisibo/Delayed Asset/Delayed Asset Proxy")] 32 | public class DelayedAssetProxy : ScriptableObject 33 | { 34 | // The original asset, which can be inside any folder: 35 | [SerializeField, HideInInspector] UnityEngine.Object asset = null; 36 | 37 | 38 | /// The original asset. 39 | public UnityEngine.Object Asset 40 | { 41 | get { return asset; } 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Assets/Trisibo/Delayed asset/DelayedAssetTypeAttribute.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2017 Trinidad Sibajas Bodoque 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | 22 | using UnityEngine; 23 | using System; 24 | 25 | namespace Trisibo 26 | { 27 | /// 28 | /// Allows to specify the wrapped type for a . 29 | /// 30 | 31 | [AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false)] 32 | public sealed class DelayedAssetTypeAttribute : PropertyAttribute 33 | { 34 | public readonly Type Type; 35 | 36 | public DelayedAssetTypeAttribute(Type type) 37 | { 38 | if (!typeof(UnityEngine.Object).IsAssignableFrom(type)) 39 | throw new ArgumentException("The type argument for a DelayedAssetTypeAttribute must be derived from Unity.Object"); 40 | 41 | this.Type = type; 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Assets/Trisibo/Delayed asset/Editor/DelayedAssetDrawer.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2017 Trinidad Sibajas Bodoque 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | 22 | using UnityEngine; 23 | using UnityEditor; 24 | using System; 25 | 26 | namespace Trisibo 27 | { 28 | [CustomPropertyDrawer(typeof(DelayedAsset))] 29 | public class DelayedAssetDrawer : PropertyDrawer 30 | { 31 | bool isDraggingValidProxy; 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | /// 41 | /// implementation. 42 | /// 43 | 44 | public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) 45 | { 46 | // Check if the field has a type attribute, and get the type: 47 | DelayedAssetTypeAttribute typeAttribute = (DelayedAssetTypeAttribute)Attribute.GetCustomAttribute(fieldInfo, typeof(DelayedAssetTypeAttribute)); 48 | Type desiredType = typeAttribute != null ? typeAttribute.Type : typeof(UnityEngine.Object); 49 | 50 | 51 | // If a DelayedAssetProxy is being dragged into the slot, and the type of the referenced asset matches the desired type, allow to set it: 52 | if (Event.current.type == EventType.DragUpdated) 53 | { 54 | UnityEngine.Object draggedObject = DragAndDrop.objectReferences.Length == 0 ? null : DragAndDrop.objectReferences[0]; 55 | isDraggingValidProxy = draggedObject is DelayedAssetProxy && ((DelayedAssetProxy)draggedObject).Asset != null && desiredType.IsAssignableFrom(((DelayedAssetProxy)draggedObject).Asset.GetType()) && position.Contains(Event.current.mousePosition); 56 | } 57 | else if (Event.current.type == EventType.DragExited) 58 | { 59 | isDraggingValidProxy = false; 60 | } 61 | 62 | 63 | if (isDraggingValidProxy) 64 | desiredType = typeof(DelayedAssetProxy); 65 | 66 | 67 | // Begin the property: 68 | EditorGUI.BeginProperty(position, label, property); 69 | EditorGUI.BeginDisabledGroup(EditorApplication.isPlayingOrWillChangePlaymode); 70 | 71 | 72 | // Draw the property: 73 | SerializedProperty assetProperty = property.FindPropertyRelative("asset"); 74 | label.text = GetFormattedLabel(label.text); 75 | 76 | EditorGUI.BeginChangeCheck(); 77 | EditorGUI.showMixedValue = property.hasMultipleDifferentValues; 78 | UnityEngine.Object newAsset = EditorGUI.ObjectField(position, label, assetProperty.objectReferenceValue, desiredType, false); 79 | EditorGUI.showMixedValue = false; 80 | 81 | bool hasChanged = EditorGUI.EndChangeCheck(); 82 | if (hasChanged) 83 | assetProperty.objectReferenceValue = newAsset; 84 | 85 | 86 | // If an object has been assigned, check if there is some problem with it: 87 | if (hasChanged && newAsset != null) 88 | { 89 | string error = DelayedAsset.CheckForErrors(newAsset, DelayedAsset.GetResourcesRelativeAssetPath(AssetDatabase.GetAssetPath(newAsset))); 90 | if (error != null) 91 | { 92 | assetProperty.objectReferenceValue = null; 93 | EditorUtility.DisplayDialog("Delayed asset error", error, "OK"); 94 | Debug.LogError("Delayed asset error: " + error); 95 | } 96 | } 97 | 98 | 99 | // End of the property: 100 | EditorGUI.EndDisabledGroup(); 101 | EditorGUI.EndProperty(); 102 | } 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | /// 112 | /// Gets a formatted label for the field. 113 | /// 114 | /// The original label. 115 | /// The formatted label. 116 | 117 | static string GetFormattedLabel(string originalLabel) 118 | { 119 | return "{" + originalLabel + "}"; 120 | } 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /Assets/Trisibo/Delayed asset/Editor/DelayedAssetProxyEditor.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2017 Trinidad Sibajas Bodoque 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | 22 | using UnityEditor; 23 | 24 | namespace Trisibo 25 | { 26 | [CustomEditor(typeof(DelayedAssetProxy))] 27 | public class DelayedAssetProxyEditor : Editor 28 | { 29 | SerializedProperty assetProp; 30 | 31 | 32 | 33 | 34 | /// 35 | /// Implementation of Editor.OnEnable(). 36 | /// 37 | 38 | void OnEnable() 39 | { 40 | if (assetProp == null) 41 | assetProp = serializedObject.FindProperty("asset"); 42 | } 43 | 44 | 45 | 46 | 47 | /// 48 | /// Implementation of . 49 | /// 50 | 51 | public override void OnInspectorGUI() 52 | { 53 | serializedObject.Update(); 54 | 55 | EditorGUI.BeginDisabledGroup(EditorApplication.isPlayingOrWillChangePlaymode); 56 | EditorGUILayout.PropertyField(assetProp); 57 | EditorGUI.EndDisabledGroup(); 58 | 59 | serializedObject.ApplyModifiedProperties(); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /Assets/Trisibo/Delayed asset/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (C) 2017 Trinidad Sibajas Bodoque 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /Assets/Trisibo/Delayed asset/Readme.txt: -------------------------------------------------------------------------------- 1 | DEPRECATED: Causes issues with Unity at least from 2019.4 2 | ============================================================= 3 | 4 | From Unity 2019.4 (may happen in earlier versions), this plugin can cause important edit-time issues in some situations, so don't use. It may not be updated to fix the issues. Please, use Unity's "Addressable Asset System" instead (https://blogs.unity3d.com/2019/07/15/addressable-asset-system/). 5 | 6 | 7 | 8 | License 9 | ------- 10 | 11 | Copyright (C) 2017 Trinidad Sibajas Bodoque 12 | 13 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 18 | -------------------------------------------------------------------------------- /Delayed asset.unitypackage: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Trisibo/Unity-delayed-asset/c6bf8bbd730f8b6d7dc4ebbdfb5493e888d02185/Delayed asset.unitypackage -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2017 Trinidad Sibajas Bodoque 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | DEPRECATED: Causes issues with Unity at least from 2019.4 2 | ============================================================= 3 | 4 | From Unity 2019.4 (may happen in earlier versions), this plugin can cause important edit-time issues in some situations, so don't use. It may not be updated to fix the issues. Please, use Unity's "Addressable Asset System" instead (https://blogs.unity3d.com/2019/07/15/addressable-asset-system/). 5 | 6 | 7 | 8 | License 9 | ------- 10 | 11 | Copyright (C) 2017 Trinidad Sibajas Bodoque 12 | 13 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 18 | --------------------------------------------------------------------------------