public SceneBundleHandle StealBundle() { SceneBundleHandle sceneBundleHandle = _SceneBundleHandle; _SceneBundleHandle = null; return(sceneBundleHandle); }
private static void ReleaseBundle(SceneBundleHandle sceneBundleHandle) { var bundlePath = sceneBundleHandle._bundlePath; if (UnloadingBundles.ContainsKey(bundlePath)) { throw new InvalidOperationException($"Attempting to release a bundle that is already unloading! {bundlePath}"); } if (!LoadedBundles.ContainsKey(bundlePath)) { throw new InvalidOperationException($"Attempting to release a bundle is not contained within LoadedBundles! {bundlePath}"); } LoadedBundles.Remove(bundlePath); UnloadingBundles[bundlePath] = sceneBundleHandle; }
private void UpdateBlocking() { if (_LoadingStatus == LoadingStatus.Completed) { return; } if (_SceneSize == 0) { return; } try { _StartTime = Time.realtimeSinceStartup; _FileContent = (byte *)UnsafeUtility.Malloc(_SceneSize, 16, Allocator.Persistent); ReadCommand cmd; cmd.Buffer = _FileContent; cmd.Offset = 0; cmd.Size = _SceneSize; _ReadHandle = AsyncReadManager.Read(_ScenePath, &cmd, 1); if (_ExpectedObjectReferenceCount != 0) { #if UNITY_EDITOR var resourceRequests = UnityEditorInternal.InternalEditorUtility.LoadSerializedFileAndForget(_ResourcesPathObjRefs); _ResourceObjRefs = (ReferencedUnityObjects)resourceRequests[0]; #else _SceneBundleHandle = SceneBundleHandle.CreateOrRetainBundle(_ResourcesPathObjRefs); _ResourceObjRefs = _SceneBundleHandle.AssetBundle.LoadAsset <ReferencedUnityObjects>(Path.GetFileName(_ResourcesPathObjRefs)); #endif } ScheduleSceneRead(_ResourceObjRefs); _EntityManager.ExclusiveEntityTransactionDependency.Complete(); } catch (Exception e) { _LoadingFailure = e.Message; } _LoadingStatus = LoadingStatus.Completed; }
internal static SceneBundleHandle[] LoadSceneBundles(string mainBundlePath, NativeArray <Entities.Hash128> sharedBundles, bool blocking) { var hasMainBundle = !string.IsNullOrEmpty(mainBundlePath); var bundles = new SceneBundleHandle[sharedBundles.Length + (hasMainBundle ? 1 : 0)]; if (hasMainBundle) { LogBundle($"Request main bundle {mainBundlePath}"); } if (sharedBundles.IsCreated) { for (int i = 0; i < sharedBundles.Length; i++) { var path = $"{Application.streamingAssetsPath}/{EntityScenesPaths.RelativePathFolderFor(sharedBundles[i], EntityScenesPaths.PathType.EntitiesSharedReferencesBundle, -1)}"; LogBundle($"Request dependency {mainBundlePath}"); bundles[i + 1] = CreateOrRetainBundle(path); } } if (hasMainBundle) { bundles[0] = CreateOrRetainBundle(mainBundlePath); } if (blocking) { foreach (var b in bundles) { var forceLoad = b.AssetBundle; if (forceLoad == null) { Debug.LogWarning($"Failed to load asset bundle at path {b._bundlePath}"); } } } return(bundles); }
internal static SceneBundleHandle CreateOrRetainBundle(string bundlePath) { if (bundlePath == null) { throw new InvalidOperationException("Bundle Path is null!"); } // First Check if we have it loaded if (!LoadedBundles.TryGetValue(bundlePath, out var assetBundleHandle)) { // Check if it's about to be unloaded if (!UnloadingBundles.TryRemove(bundlePath, out assetBundleHandle)) { assetBundleHandle = new SceneBundleHandle(bundlePath); } LoadedBundles[bundlePath] = assetBundleHandle; } assetBundleHandle.Retain(); return(assetBundleHandle); }
private void UpdateAsync() { //@TODO: Try to overlap Resources load and entities scene load // Begin Async resource load if (_LoadingStatus == LoadingStatus.NotStarted) { if (_SceneSize == 0) { return; } try { _StartTime = Time.realtimeSinceStartup; _FileContent = (byte *)UnsafeUtility.Malloc(_SceneSize, 16, Allocator.Persistent); ReadCommand cmd; cmd.Buffer = _FileContent; cmd.Offset = 0; cmd.Size = _SceneSize; _ReadHandle = AsyncReadManager.Read(_ScenePath, &cmd, 1); if (_ExpectedObjectReferenceCount != 0) { #if UNITY_EDITOR var resourceRequests = UnityEditorInternal.InternalEditorUtility.LoadSerializedFileAndForget(_ResourcesPathObjRefs); _ResourceObjRefs = (ReferencedUnityObjects)resourceRequests[0]; _LoadingStatus = LoadingStatus.WaitingForResourcesLoad; #else _SceneBundleHandle = SceneBundleHandle.CreateOrRetainBundle(_ResourcesPathObjRefs); _LoadingStatus = LoadingStatus.WaitingForAssetBundleLoad; #endif } else { _LoadingStatus = LoadingStatus.WaitingForEntitiesLoad; } } catch (Exception e) { _LoadingFailure = e.Message; _LoadingStatus = LoadingStatus.Completed; } } // Once async asset bundle load is done, we can read the asset if (_LoadingStatus == LoadingStatus.WaitingForAssetBundleLoad) { if (!_SceneBundleHandle.IsReady()) { return; } if (!_SceneBundleHandle.AssetBundle) { _LoadingFailure = $"Failed to load Asset Bundle '{_ResourcesPathObjRefs}'"; _LoadingStatus = LoadingStatus.Completed; return; } var fileName = Path.GetFileName(_ResourcesPathObjRefs); _AssetRequest = _SceneBundleHandle.AssetBundle.LoadAssetAsync(fileName); _LoadingStatus = LoadingStatus.WaitingForAssetLoad; } // Once async asset bundle load is done, we can read the asset if (_LoadingStatus == LoadingStatus.WaitingForAssetLoad) { if (!_AssetRequest.isDone) { return; } if (!_AssetRequest.asset) { _LoadingFailure = $"Failed to load Asset '{Path.GetFileName(_ResourcesPathObjRefs)}'"; _LoadingStatus = LoadingStatus.Completed; return; } _ResourceObjRefs = _AssetRequest.asset as ReferencedUnityObjects; if (_ResourceObjRefs == null) { _LoadingFailure = $"Failed to load object references resource '{_ResourcesPathObjRefs}'"; _LoadingStatus = LoadingStatus.Completed; return; } _LoadingStatus = LoadingStatus.WaitingForEntitiesLoad; } // Once async resource load is done, we can async read the entity scene data if (_LoadingStatus == LoadingStatus.WaitingForResourcesLoad) { if (_ResourceObjRefs == null) { _LoadingFailure = $"Failed to load object references resource '{_ResourcesPathObjRefs}'"; _LoadingStatus = LoadingStatus.Completed; return; } _LoadingStatus = LoadingStatus.WaitingForEntitiesLoad; } if (_LoadingStatus == LoadingStatus.WaitingForEntitiesLoad) { try { _LoadingStatus = LoadingStatus.WaitingForSceneDeserialization; ScheduleSceneRead(_ResourceObjRefs); if (_BlockUntilFullyLoaded) { _EntityManager.ExclusiveEntityTransactionDependency.Complete(); } } catch (Exception e) { _LoadingFailure = e.Message; _LoadingStatus = LoadingStatus.Completed; } } // Complete Loading status if (_LoadingStatus == LoadingStatus.WaitingForSceneDeserialization) { if (_EntityManager.ExclusiveEntityTransactionDependency.IsCompleted) { _EntityManager.ExclusiveEntityTransactionDependency.Complete(); _LoadingStatus = LoadingStatus.Completed; var currentTime = Time.realtimeSinceStartup; var totalTime = currentTime - _StartTime; System.Console.WriteLine($"Streamed scene with {totalTime * 1000,3:f0}ms latency from {_ScenePath}"); } } }
protected override void OnUpdate() { var destroySubScenes = new NativeList <Entity>(Allocator.Temp); var sceneDataFromEntity = GetComponentDataFromEntity <SceneSectionData>(); bool SceneSectionRequiresSynchronousLoading(Entity entity) => (EntityManager.GetComponentData <RequestSceneLoaded>(entity).LoadFlags & SceneLoadFlags.BlockOnStreamIn) != 0; // Sections > 0 need the external references from sections 0 and will wait for it to be loaded. // So we have to ensure sections 0 are loaded first, otherwise there's a risk of starving loading streams. var priorityList = new NativeList <Entity>(Allocator.Temp); using (var entities = m_PendingStreamRequests.ToEntityArray(Allocator.TempJob)) { var priorities = new NativeArray <int>(entities.Length, Allocator.Temp); for (int i = 0; i < entities.Length; ++i) { var entity = entities[i]; if (SceneSectionRequiresSynchronousLoading(entity)) { priorities[i] = 0; var operation = CreateAsyncLoadSceneOperation(m_SynchronousSceneLoadWorld.EntityManager, entity, true); var result = UpdateLoadOperation(operation, m_SynchronousSceneLoadWorld, entity); if (result == UpdateLoadOperationResult.Error) { m_SynchronousSceneLoadWorld.Dispose(); m_SynchronousSceneLoadWorld = new World("LoadingWorld (synchronous)"); } Assert.AreNotEqual(UpdateLoadOperationResult.Aborted, result); } else if (sceneDataFromEntity[entity].SubSectionIndex == 0) { priorities[i] = 1; } else { priorities[i] = 2; } } for (int priority = 1; priority <= 2; ++priority) { for (int i = 0; i < entities.Length; ++i) { if (priorityList.Length == LoadScenesPerFrame) { break; } if (priorities[i] == priority) { priorityList.Add(entities[i]); } } } } var priorityArray = priorityList.AsArray(); foreach (var entity in priorityArray) { var streamIndex = CreateAsyncLoadScene(entity, false); if (streamIndex != -1) { var streamingState = new StreamingState { ActiveStreamIndex = streamIndex, Status = StreamingStatus.NotYetProcessed }; EntityManager.AddComponentData(entity, streamingState); } } Entities.With(m_UnloadStreamRequests).ForEach((Entity entity) => { destroySubScenes.Add(entity); }); foreach (var destroyScene in destroySubScenes.AsArray()) { UnloadSectionImmediate(destroyScene); } if (ProcessActiveStreams()) { EditorUpdateUtility.EditModeQueuePlayerLoopUpdate(); } // Process unloading bundles SceneBundleHandle.ProcessUnloadingBundles(); }
public void Release() { _sceneBundleHandle?.Release(); _sceneBundleHandle = null; }
public SceneSectionBundle(SceneBundleHandle bundle) { _sceneBundleHandle = bundle; }