ResourceManager.cs 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. using UnityEngine;
  2. using System.Collections.Generic;
  3. #if UNITY_5_4_OR_NEWER
  4. using UnityEngine.SceneManagement;
  5. #endif
  6. namespace I2.Loc
  7. {
  8. public interface IResourceManager_Bundles
  9. {
  10. Object LoadFromBundle(string path, System.Type assetType );
  11. }
  12. public class ResourceManager : MonoBehaviour
  13. {
  14. #region Singleton
  15. public static ResourceManager pInstance
  16. {
  17. get {
  18. bool changed = mInstance==null;
  19. if (mInstance==null)
  20. mInstance = (ResourceManager)FindObjectOfType(typeof(ResourceManager));
  21. if (mInstance==null)
  22. {
  23. GameObject GO = new GameObject("I2ResourceManager", typeof(ResourceManager));
  24. GO.hideFlags = GO.hideFlags | HideFlags.HideAndDontSave; // Only hide it if this manager was autocreated
  25. mInstance = GO.GetComponent<ResourceManager>();
  26. #if UNITY_5_4_OR_NEWER
  27. SceneManager.sceneLoaded += MyOnLevelWasLoaded;
  28. #endif
  29. }
  30. if (changed && Application.isPlaying)
  31. DontDestroyOnLoad(mInstance.gameObject);
  32. return mInstance;
  33. }
  34. }
  35. static ResourceManager mInstance;
  36. #endregion
  37. #region Management
  38. public List<IResourceManager_Bundles> mBundleManagers = new List<IResourceManager_Bundles>();
  39. #if UNITY_5_4_OR_NEWER
  40. public static void MyOnLevelWasLoaded(Scene scene, LoadSceneMode mode)
  41. #else
  42. public void OnLevelWasLoaded()
  43. #endif
  44. {
  45. pInstance.CleanResourceCache();
  46. LocalizationManager.UpdateSources();
  47. }
  48. #endregion
  49. #region Assets
  50. public Object[] Assets;
  51. // This function tries finding an asset in the Assets array, if not found it tries loading it from the Resources Folder
  52. public T GetAsset<T>( string Name ) where T : Object
  53. {
  54. T Obj = FindAsset( Name ) as T;
  55. if (Obj!=null)
  56. return Obj;
  57. return LoadFromResources<T>( Name );
  58. }
  59. Object FindAsset( string Name )
  60. {
  61. if (Assets!=null)
  62. {
  63. for (int i=0, imax=Assets.Length; i<imax; ++i)
  64. if (Assets[i]!=null && Assets[i].name == Name)
  65. return Assets[i];
  66. }
  67. return null;
  68. }
  69. public bool HasAsset( Object Obj )
  70. {
  71. if (Assets==null)
  72. return false;
  73. return System.Array.IndexOf (Assets, Obj) >= 0;
  74. }
  75. #endregion
  76. #region Resources Cache
  77. // This cache is kept for a few moments and then cleared
  78. // Its meant to avoid doing several Resource.Load for the same Asset while Localizing
  79. // (e.g. Lot of labels could be trying to Load the same Font)
  80. readonly Dictionary<string, Object> mResourcesCache = new Dictionary<string, Object>(System.StringComparer.Ordinal); // This is used to avoid re-loading the same object from resources in the same frame
  81. //bool mCleaningScheduled = false;
  82. public T LoadFromResources<T>( string Path ) where T : Object
  83. {
  84. try
  85. {
  86. if (string.IsNullOrEmpty( Path ))
  87. return null;
  88. Object Obj;
  89. // Doing Resource.Load is very slow so we are catching the recently loaded objects
  90. if (mResourcesCache.TryGetValue( Path, out Obj ) && Obj!=null)
  91. {
  92. return Obj as T;
  93. }
  94. T obj = null;
  95. if (Path.EndsWith("]", System.StringComparison.OrdinalIgnoreCase)) // Handle sprites (Multiple) loaded from resources : "SpritePath[SpriteName]"
  96. {
  97. int idx = Path.LastIndexOf("[", System.StringComparison.OrdinalIgnoreCase);
  98. int len = Path.Length - idx - 2;
  99. string MultiSpriteName = Path.Substring(idx + 1, len);
  100. Path = Path.Substring(0, idx);
  101. T[] objs = Resources.LoadAll<T>(Path);
  102. for (int j = 0, jmax = objs.Length; j < jmax; ++j)
  103. if (objs[j].name.Equals(MultiSpriteName))
  104. {
  105. obj = objs[j];
  106. break;
  107. }
  108. }
  109. else
  110. {
  111. obj = Resources.Load(Path, typeof(T)) as T;
  112. }
  113. if (obj == null)
  114. obj = LoadFromBundle<T>( Path );
  115. if (obj!=null)
  116. mResourcesCache[Path] = obj;
  117. /*if (!mCleaningScheduled)
  118. {
  119. Invoke("CleanResourceCache", 0.1f);
  120. mCleaningScheduled = true;
  121. }*/
  122. //if (obj==null)
  123. //Debug.LogWarningFormat( "Unable to load {0} '{1}'", typeof( T ), Path );
  124. return obj;
  125. }
  126. catch (System.Exception e)
  127. {
  128. Debug.LogErrorFormat( "Unable to load {0} '{1}'\nERROR: {2}", typeof(T), Path, e.ToString() );
  129. return null;
  130. }
  131. }
  132. public T LoadFromBundle<T>(string path ) where T : Object
  133. {
  134. for (int i = 0, imax = mBundleManagers.Count; i < imax; ++i)
  135. if (mBundleManagers[i]!=null)
  136. {
  137. var obj = mBundleManagers[i].LoadFromBundle(path, typeof(T)) as T;
  138. if (obj != null)
  139. return obj;
  140. }
  141. return null;
  142. }
  143. public void CleanResourceCache()
  144. {
  145. mResourcesCache.Clear();
  146. Resources.UnloadUnusedAssets();
  147. CancelInvoke();
  148. //mCleaningScheduled = false;
  149. }
  150. #endregion
  151. }
  152. }