using System; using System.Collections.Generic; using UnityEngine.Networking; using UnityEngine.ResourceManagement.Util; namespace UnityEngine.ResourceManagement { /// /// Represents a web request stored in the . /// public class WebRequestQueueOperation { private bool m_Completed = false; /// /// Stores the async operation object returned from sending the web request. /// public UnityWebRequestAsyncOperation Result; /// /// Event that is invoked when the async operation is complete. /// public Action OnComplete; /// /// Indicates that the async operation is complete. /// public bool IsDone { get { return m_Completed || Result != null; } } internal UnityWebRequest m_WebRequest; /// /// The web request. /// public UnityWebRequest WebRequest { get { return m_WebRequest; } internal set { m_WebRequest = value; } } /// /// Initializes and returns an instance of WebRequestQueueOperation. /// /// The web request associated with this object. public WebRequestQueueOperation(UnityWebRequest request) { m_WebRequest = request; } internal void Complete(UnityWebRequestAsyncOperation asyncOp) { m_Completed = true; Result = asyncOp; OnComplete?.Invoke(Result); } } /// /// Represents a queue of web requests. Completed requests are removed from the queue. /// public static class WebRequestQueue { internal static int s_MaxRequest = 3; internal static Queue s_QueuedOperations = new Queue(); internal static List s_ActiveRequests = new List(); /// /// Sets the max number of web requests running at the same time. /// /// The max number of web requests. public static void SetMaxConcurrentRequests(int maxRequests) { if (maxRequests < 1) throw new ArgumentException("MaxRequests must be 1 or greater.", "maxRequests"); s_MaxRequest = maxRequests; } /// /// Adds a web request to the queue. /// /// The web request. /// Returns an object representing the web request. public static WebRequestQueueOperation QueueRequest(UnityWebRequest request) { WebRequestQueueOperation queueOperation = new WebRequestQueueOperation(request); if (s_ActiveRequests.Count < s_MaxRequest) BeginWebRequest(queueOperation); else s_QueuedOperations.Enqueue(queueOperation); return queueOperation; } /// /// Synchronously waits for a particular web request to be completed. /// /// The web request. /// The amount of time in milliseconds spent waiting per iteration before checking if the request is complete. public static void WaitForRequestToBeActive(WebRequestQueueOperation request, int millisecondsTimeout) { var completedRequests = new List(); while (s_QueuedOperations.Contains(request)) { completedRequests.Clear(); foreach (UnityWebRequestAsyncOperation webRequestAsyncOp in s_ActiveRequests) { if (UnityWebRequestUtilities.IsAssetBundleDownloaded(webRequestAsyncOp)) completedRequests.Add(webRequestAsyncOp); } foreach (UnityWebRequestAsyncOperation webRequestAsyncOp in completedRequests) { bool requestIsActive = s_QueuedOperations.Peek() == request; webRequestAsyncOp.completed -= OnWebAsyncOpComplete; OnWebAsyncOpComplete(webRequestAsyncOp); if (requestIsActive) return; } System.Threading.Thread.Sleep(millisecondsTimeout); } } private static void OnWebAsyncOpComplete(AsyncOperation operation) { s_ActiveRequests.Remove(operation as UnityWebRequestAsyncOperation); if (s_QueuedOperations.Count > 0) { var nextQueuedOperation = s_QueuedOperations.Dequeue(); BeginWebRequest(nextQueuedOperation); } } static void BeginWebRequest(WebRequestQueueOperation queueOperation) { var request = queueOperation.m_WebRequest; UnityWebRequestAsyncOperation webRequestAsyncOp = null; try { webRequestAsyncOp = request.SendWebRequest(); if (webRequestAsyncOp != null) { s_ActiveRequests.Add(webRequestAsyncOp); if (webRequestAsyncOp.isDone) OnWebAsyncOpComplete(webRequestAsyncOp); else webRequestAsyncOp.completed += OnWebAsyncOpComplete; } else { OnWebAsyncOpComplete(null); } } catch (Exception e) { Debug.LogError(e.Message); } queueOperation.Complete(webRequestAsyncOp); } } }