InstantiateOperation.cs 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. using UnityEngine;
  2. namespace YooAsset
  3. {
  4. public sealed class InstantiateOperation : AsyncOperationBase
  5. {
  6. private enum ESteps
  7. {
  8. None,
  9. LoadObject,
  10. CloneSync,
  11. CloneAsync,
  12. Done,
  13. }
  14. private readonly AssetHandle _handle;
  15. private readonly bool _setPositionAndRotation;
  16. private readonly Vector3 _position;
  17. private readonly Quaternion _rotation;
  18. private readonly Transform _parent;
  19. private readonly bool _worldPositionStays;
  20. private readonly bool _actived;
  21. private ESteps _steps = ESteps.None;
  22. #if UNITY_2023_3_OR_NEWER
  23. private AsyncInstantiateOperation _instantiateAsync;
  24. #endif
  25. /// <summary>
  26. /// 实例化的游戏对象
  27. /// </summary>
  28. public GameObject Result = null;
  29. internal InstantiateOperation(AssetHandle handle, bool setPositionAndRotation, Vector3 position, Quaternion rotation,
  30. Transform parent, bool worldPositionStays, bool actived)
  31. {
  32. _handle = handle;
  33. _setPositionAndRotation = setPositionAndRotation;
  34. _position = position;
  35. _rotation = rotation;
  36. _parent = parent;
  37. _worldPositionStays = worldPositionStays;
  38. _actived = actived;
  39. }
  40. internal override void InternalStart()
  41. {
  42. _steps = ESteps.LoadObject;
  43. }
  44. internal override void InternalUpdate()
  45. {
  46. if (_steps == ESteps.None || _steps == ESteps.Done)
  47. return;
  48. if (_steps == ESteps.LoadObject)
  49. {
  50. if (_handle.IsValidWithWarning == false)
  51. {
  52. _steps = ESteps.Done;
  53. Status = EOperationStatus.Failed;
  54. Error = $"{nameof(AssetHandle)} is invalid.";
  55. return;
  56. }
  57. if (_handle.IsDone == false)
  58. return;
  59. if (_handle.AssetObject == null)
  60. {
  61. _steps = ESteps.Done;
  62. Status = EOperationStatus.Failed;
  63. Error = $"{nameof(AssetHandle.AssetObject)} is null.";
  64. return;
  65. }
  66. #if UNITY_2023_3_OR_NEWER
  67. //TODO 官方BUG
  68. // BUG环境:Windows平台,Unity2022.3.41f1版本,编辑器模式。
  69. // BUG描述:异步实例化Prefab预制体,有概率丢失Mono脚本里序列化的数组里某个成员!
  70. //_steps = ESteps.CloneAsync;
  71. _steps = ESteps.CloneSync;
  72. #else
  73. _steps = ESteps.CloneSync;
  74. #endif
  75. }
  76. if (_steps == ESteps.CloneSync)
  77. {
  78. // 实例化游戏对象
  79. Result = InstantiateInternal(_handle.AssetObject, _setPositionAndRotation, _position, _rotation, _parent, _worldPositionStays);
  80. if (_actived == false)
  81. Result.SetActive(false);
  82. _steps = ESteps.Done;
  83. Status = EOperationStatus.Succeed;
  84. }
  85. #if UNITY_2023_3_OR_NEWER
  86. if (_steps == ESteps.CloneAsync)
  87. {
  88. if (_instantiateAsync == null)
  89. {
  90. _instantiateAsync = InstantiateAsyncInternal(_handle.AssetObject, _setPositionAndRotation, _position, _rotation, _parent, _worldPositionStays);
  91. }
  92. if (IsWaitForAsyncComplete)
  93. _instantiateAsync.WaitForCompletion();
  94. if (_instantiateAsync.isDone == false)
  95. return;
  96. if (_instantiateAsync.Result != null && _instantiateAsync.Result.Length > 0)
  97. {
  98. Result = _instantiateAsync.Result[0] as GameObject;
  99. if (Result != null)
  100. {
  101. if (_actived == false)
  102. Result.SetActive(false);
  103. _steps = ESteps.Done;
  104. Status = EOperationStatus.Succeed;
  105. }
  106. else
  107. {
  108. _steps = ESteps.Done;
  109. Status = EOperationStatus.Failed;
  110. Error = $"Instantiate game object is null !";
  111. }
  112. }
  113. else
  114. {
  115. _steps = ESteps.Done;
  116. Status = EOperationStatus.Failed;
  117. Error = $"Instantiate async results is null !";
  118. }
  119. }
  120. #endif
  121. }
  122. internal override void InternalWaitForAsyncComplete()
  123. {
  124. while (true)
  125. {
  126. // 等待句柄完成
  127. if (_handle != null)
  128. _handle.WaitForAsyncComplete();
  129. if (ExecuteWhileDone())
  130. {
  131. _steps = ESteps.Done;
  132. break;
  133. }
  134. }
  135. }
  136. internal override string InternalGetDesc()
  137. {
  138. var assetInfo = _handle.GetAssetInfo();
  139. return $"AssetPath : {assetInfo.AssetPath}";
  140. }
  141. /// <summary>
  142. /// 取消实例化对象操作
  143. /// </summary>
  144. public void Cancel()
  145. {
  146. #if UNITY_2023_3_OR_NEWER
  147. if (_instantiateAsync != null && _instantiateAsync.isDone == false)
  148. _instantiateAsync.Cancel();
  149. #endif
  150. AbortOperation();
  151. }
  152. /// <summary>
  153. /// 同步实例化
  154. /// </summary>
  155. internal static GameObject InstantiateInternal(UnityEngine.Object assetObject, bool setPositionAndRotation, Vector3 position, Quaternion rotation, Transform parent, bool worldPositionStays)
  156. {
  157. if (assetObject == null)
  158. return null;
  159. if (setPositionAndRotation)
  160. {
  161. if (parent != null)
  162. return UnityEngine.Object.Instantiate(assetObject as GameObject, position, rotation, parent);
  163. else
  164. return UnityEngine.Object.Instantiate(assetObject as GameObject, position, rotation);
  165. }
  166. else
  167. {
  168. if (parent != null)
  169. return UnityEngine.Object.Instantiate(assetObject as GameObject, parent, worldPositionStays);
  170. else
  171. return UnityEngine.Object.Instantiate(assetObject as GameObject);
  172. }
  173. }
  174. #if UNITY_2023_3_OR_NEWER
  175. /// <summary>
  176. /// 异步实例化
  177. /// 注意:Unity2022.3.20f1及以上版本生效
  178. /// https://docs.unity3d.com/2022.3/Documentation/ScriptReference/Object.InstantiateAsync.html
  179. /// </summary>
  180. internal static AsyncInstantiateOperation InstantiateAsyncInternal(UnityEngine.Object assetObject, bool setPositionAndRotation, Vector3 position, Quaternion rotation, Transform parent, bool worldPositionStays)
  181. {
  182. if (setPositionAndRotation)
  183. {
  184. if (parent != null)
  185. return UnityEngine.Object.InstantiateAsync(assetObject as GameObject, parent, position, rotation);
  186. else
  187. return UnityEngine.Object.InstantiateAsync(assetObject as GameObject, position, rotation);
  188. }
  189. else
  190. {
  191. if (parent != null)
  192. return UnityEngine.Object.InstantiateAsync(assetObject as GameObject, parent);
  193. else
  194. return UnityEngine.Object.InstantiateAsync(assetObject as GameObject);
  195. }
  196. }
  197. #endif
  198. }
  199. }