Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
 
 
 

254 lignes
9.3 KiB

  1. #pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
  2. #if UNITY_2018_4 || UNITY_2019_4_OR_NEWER
  3. #if UNITASK_ASSETBUNDLE_SUPPORT
  4. using Cysharp.Threading.Tasks.Internal;
  5. using System;
  6. using System.Runtime.CompilerServices;
  7. using System.Threading;
  8. using UnityEngine;
  9. namespace Cysharp.Threading.Tasks
  10. {
  11. public static partial class UnityAsyncExtensions
  12. {
  13. public static AssetBundleRequestAllAssetsAwaiter AwaitForAllAssets(this AssetBundleRequest asyncOperation)
  14. {
  15. Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
  16. return new AssetBundleRequestAllAssetsAwaiter(asyncOperation);
  17. }
  18. public static UniTask<UnityEngine.Object[]> AwaitForAllAssets(this AssetBundleRequest asyncOperation, CancellationToken cancellationToken)
  19. {
  20. return AwaitForAllAssets(asyncOperation, null, PlayerLoopTiming.Update, cancellationToken: cancellationToken);
  21. }
  22. public static UniTask<UnityEngine.Object[]> AwaitForAllAssets(this AssetBundleRequest asyncOperation, CancellationToken cancellationToken, bool cancelImmediately)
  23. {
  24. return AwaitForAllAssets(asyncOperation, progress: null, cancellationToken: cancellationToken, cancelImmediately: cancelImmediately);
  25. }
  26. public static UniTask<UnityEngine.Object[]> AwaitForAllAssets(this AssetBundleRequest asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
  27. {
  28. Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
  29. if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<UnityEngine.Object[]>(cancellationToken);
  30. if (asyncOperation.isDone) return UniTask.FromResult(asyncOperation.allAssets);
  31. return new UniTask<UnityEngine.Object[]>(AssetBundleRequestAllAssetsConfiguredSource.Create(asyncOperation, timing, progress, cancellationToken, cancelImmediately, out var token), token);
  32. }
  33. public struct AssetBundleRequestAllAssetsAwaiter : ICriticalNotifyCompletion
  34. {
  35. AssetBundleRequest asyncOperation;
  36. Action<AsyncOperation> continuationAction;
  37. public AssetBundleRequestAllAssetsAwaiter(AssetBundleRequest asyncOperation)
  38. {
  39. this.asyncOperation = asyncOperation;
  40. this.continuationAction = null;
  41. }
  42. public AssetBundleRequestAllAssetsAwaiter GetAwaiter()
  43. {
  44. return this;
  45. }
  46. public bool IsCompleted => asyncOperation.isDone;
  47. public UnityEngine.Object[] GetResult()
  48. {
  49. if (continuationAction != null)
  50. {
  51. asyncOperation.completed -= continuationAction;
  52. continuationAction = null;
  53. var result = asyncOperation.allAssets;
  54. asyncOperation = null;
  55. return result;
  56. }
  57. else
  58. {
  59. var result = asyncOperation.allAssets;
  60. asyncOperation = null;
  61. return result;
  62. }
  63. }
  64. public void OnCompleted(Action continuation)
  65. {
  66. UnsafeOnCompleted(continuation);
  67. }
  68. public void UnsafeOnCompleted(Action continuation)
  69. {
  70. Error.ThrowWhenContinuationIsAlreadyRegistered(continuationAction);
  71. continuationAction = PooledDelegate<AsyncOperation>.Create(continuation);
  72. asyncOperation.completed += continuationAction;
  73. }
  74. }
  75. sealed class AssetBundleRequestAllAssetsConfiguredSource : IUniTaskSource<UnityEngine.Object[]>, IPlayerLoopItem, ITaskPoolNode<AssetBundleRequestAllAssetsConfiguredSource>
  76. {
  77. static TaskPool<AssetBundleRequestAllAssetsConfiguredSource> pool;
  78. AssetBundleRequestAllAssetsConfiguredSource nextNode;
  79. public ref AssetBundleRequestAllAssetsConfiguredSource NextNode => ref nextNode;
  80. static AssetBundleRequestAllAssetsConfiguredSource()
  81. {
  82. TaskPool.RegisterSizeGetter(typeof(AssetBundleRequestAllAssetsConfiguredSource), () => pool.Size);
  83. }
  84. AssetBundleRequest asyncOperation;
  85. IProgress<float> progress;
  86. CancellationToken cancellationToken;
  87. CancellationTokenRegistration cancellationTokenRegistration;
  88. bool cancelImmediately;
  89. bool completed;
  90. UniTaskCompletionSourceCore<UnityEngine.Object[]> core;
  91. Action<AsyncOperation> continuationAction;
  92. AssetBundleRequestAllAssetsConfiguredSource()
  93. {
  94. continuationAction = Continuation;
  95. }
  96. public static IUniTaskSource<UnityEngine.Object[]> Create(AssetBundleRequest asyncOperation, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, bool cancelImmediately, out short token)
  97. {
  98. if (cancellationToken.IsCancellationRequested)
  99. {
  100. return AutoResetUniTaskCompletionSource<UnityEngine.Object[]>.CreateFromCanceled(cancellationToken, out token);
  101. }
  102. if (!pool.TryPop(out var result))
  103. {
  104. result = new AssetBundleRequestAllAssetsConfiguredSource();
  105. }
  106. result.asyncOperation = asyncOperation;
  107. result.progress = progress;
  108. result.cancellationToken = cancellationToken;
  109. result.cancelImmediately = cancelImmediately;
  110. result.completed = false;
  111. asyncOperation.completed += result.continuationAction;
  112. if (cancelImmediately && cancellationToken.CanBeCanceled)
  113. {
  114. result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
  115. {
  116. var source = (AssetBundleRequestAllAssetsConfiguredSource)state;
  117. source.core.TrySetCanceled(source.cancellationToken);
  118. }, result);
  119. }
  120. TaskTracker.TrackActiveTask(result, 3);
  121. PlayerLoopHelper.AddAction(timing, result);
  122. token = result.core.Version;
  123. return result;
  124. }
  125. public UnityEngine.Object[] GetResult(short token)
  126. {
  127. try
  128. {
  129. return core.GetResult(token);
  130. }
  131. finally
  132. {
  133. if (!(cancelImmediately && cancellationToken.IsCancellationRequested))
  134. {
  135. TryReturn();
  136. }
  137. else
  138. {
  139. TaskTracker.RemoveTracking(this);
  140. }
  141. }
  142. }
  143. void IUniTaskSource.GetResult(short token)
  144. {
  145. GetResult(token);
  146. }
  147. public UniTaskStatus GetStatus(short token)
  148. {
  149. return core.GetStatus(token);
  150. }
  151. public UniTaskStatus UnsafeGetStatus()
  152. {
  153. return core.UnsafeGetStatus();
  154. }
  155. public void OnCompleted(Action<object> continuation, object state, short token)
  156. {
  157. core.OnCompleted(continuation, state, token);
  158. }
  159. public bool MoveNext()
  160. {
  161. // Already completed
  162. if (completed || asyncOperation == null)
  163. {
  164. return false;
  165. }
  166. if (cancellationToken.IsCancellationRequested)
  167. {
  168. core.TrySetCanceled(cancellationToken);
  169. return false;
  170. }
  171. if (progress != null)
  172. {
  173. progress.Report(asyncOperation.progress);
  174. }
  175. if (asyncOperation.isDone)
  176. {
  177. core.TrySetResult(asyncOperation.allAssets);
  178. return false;
  179. }
  180. return true;
  181. }
  182. bool TryReturn()
  183. {
  184. TaskTracker.RemoveTracking(this);
  185. core.Reset();
  186. asyncOperation = default;
  187. progress = default;
  188. cancellationToken = default;
  189. cancellationTokenRegistration.Dispose();
  190. cancelImmediately = default;
  191. return pool.TryPush(this);
  192. }
  193. void Continuation(AsyncOperation _)
  194. {
  195. if (completed)
  196. {
  197. return;
  198. }
  199. completed = true;
  200. if (cancellationToken.IsCancellationRequested)
  201. {
  202. core.TrySetCanceled(cancellationToken);
  203. }
  204. else
  205. {
  206. core.TrySetResult(asyncOperation.allAssets);
  207. }
  208. }
  209. }
  210. }
  211. }
  212. #endif
  213. #endif