Exemplo n.º 1
0
        private static unsafe void WriteEntitySceneWithBuildConfig(Hash128 guid, SceneWithBuildConfigurationGUIDs sceneWithBuildConfigurationGUIDs, string path)
        {
            var previousPath = AssetDatabaseCompatibility.GuidToPath(guid);

            if (!string.IsNullOrEmpty(previousPath) && previousPath != path)
            {
                UnityEngine.Debug.LogError($"EntitySceneWithBuildConfig guid is not unique {guid}. ScenePath: '{AssetDatabaseCompatibility.GuidToPath(sceneWithBuildConfigurationGUIDs.SceneGUID)}' Conflicting GUID: '{previousPath}'");
            }

            Directory.CreateDirectory(k_SceneDependencyCachePath);
            using (var writer = new StreamBinaryWriter(path))
            {
                writer.WriteBytes(&sceneWithBuildConfigurationGUIDs, sizeof(SceneWithBuildConfigurationGUIDs));
            }
            File.WriteAllText(path + ".meta",
                              $"fileFormatVersion: 2\nguid: {guid}\nDefaultImporter:\n  externalObjects: {{}}\n  userData:\n  assetBundleName:\n  assetBundleVariant:\n");
        }
        protected override void OnUpdate()
        {
            SceneWithBuildConfigurationGUIDs.ValidateBuildSettingsCache();

            var sceneSystem            = World.GetExistingSystem <SceneSystem>();
            var buildConfigurationGUID = sceneSystem.BuildConfigurationGUID;

            // Add scene entities that haven't been encountered yet
            if (!m_AddScenes.IsEmptyIgnoreFilter)
            {
                //@TODO: Should use Entities.ForEach but we are missing
                // 1. Entities.ForEach support with execute always (ILPP compilation not taking effect on first domain reload)
                // 2. Entities.ForEach not supporting explicit queries

                using (var addScenes = m_AddScenes.ToEntityArray(Allocator.TempJob))
                {
                    var trackerStates = new NativeArray <AssetDependencyTrackerState>(addScenes.Length, Allocator.Temp);
                    for (int i = 0; i != addScenes.Length; i++)
                    {
                        var sceneEntity        = addScenes[i];
                        var scene              = EntityManager.GetComponentData <SceneReference>(sceneEntity);
                        var requestSceneLoaded = EntityManager.GetComponentData <RequestSceneLoaded>(sceneEntity);

                        var guid = SceneWithBuildConfigurationGUIDs.EnsureExistsFor(scene.SceneGUID,
                                                                                    buildConfigurationGUID, out var requireRefresh);
                        var async = (requestSceneLoaded.LoadFlags & SceneLoadFlags.BlockOnImport) == 0;

                        LogResolving(async ? "Adding Async" : "Adding Sync", guid);

                        _AssetDependencyTracker.Add(guid, sceneEntity, async);
                        if (requireRefresh)
                        {
                            _AssetDependencyTracker.RequestRefresh();
                        }

                        trackerStates[i] = new AssetDependencyTrackerState {
                            SceneAndBuildConfigGUID = guid
                        };
                    }

                    EntityManager.AddComponentData(m_AddScenes, trackerStates);
                    trackerStates.Dispose();
                }
            }

            // Remove scene entities that were added and should no longer be tracked
            if (!m_RemoveScenes.IsEmptyIgnoreFilter)
            {
                using (var removeEntities = m_RemoveScenes.ToEntityArray(Allocator.TempJob))
                    using (var removeGuids =
                               m_RemoveScenes.ToComponentDataArray <AssetDependencyTrackerState>(Allocator.TempJob))
                    {
                        for (int i = 0; i != removeEntities.Length; i++)
                        {
                            LogResolving("Removing", removeGuids[i].SceneAndBuildConfigGUID);
                            _AssetDependencyTracker.Remove(removeGuids[i].SceneAndBuildConfigGUID, removeEntities[i]);
                        }
                    }

                EntityManager.RemoveComponent <AssetDependencyTrackerState>(m_RemoveScenes);
            }

            // Process any scenes that have completed their asset import
            var isDone = _AssetDependencyTracker.GetCompleted(_Changed);

            foreach (var change in _Changed)
            {
                var sceneEntity = change.UserKey;
                LogResolving($"Resolving: {change.Asset} -> {change.ArtifactID}");

                if (!m_ValidSceneMask.Matches(sceneEntity))
                {
                    throw new InvalidOperationException("entity should have been removed from tracker already");
                }

                // Unload any previous state
                var unloadFlags = SceneSystem.UnloadParameters.DestroySectionProxyEntities |
                                  SceneSystem.UnloadParameters.DontRemoveRequestSceneLoaded;
                sceneSystem.UnloadScene(sceneEntity, unloadFlags);

                // Resolve new state
                var scene   = EntityManager.GetComponentData <SceneReference>(change.UserKey);
                var request = EntityManager.GetComponentData <RequestSceneLoaded>(change.UserKey);
                if (change.ArtifactID != default)
                {
                    ResolveSceneSectionUtility.ResolveSceneSections(EntityManager, change.UserKey, scene.SceneGUID,
                                                                    request, change.ArtifactID);
                }
                else
                {
                    Debug.LogError(
                        $"Failed to import entity scene because the automatically generated SceneAndBuildConfigGUID asset was not present: '{AssetDatabaseCompatibility.GuidToPath(scene.SceneGUID)}' -> '{AssetDatabaseCompatibility.GuidToPath(change.Asset)}'");
                }
            }

            if (!isDone)
            {
                EditorUpdateUtility.EditModeQueuePlayerLoopUpdate();
            }
        }
        public unsafe static bool ResolveSceneSections(EntityManager EntityManager, Entity sceneEntity, Hash128 sceneGUID, RequestSceneLoaded requestSceneLoaded, Hash128 artifactHash)
        {
            // Resolve first (Even if the file doesn't exist we want to stop continously trying to load the section)
            var bufLen = EntityManager.AddBuffer <ResolvedSectionEntity>(sceneEntity).Length;

            Assert.AreEqual(0, bufLen);

            var sceneHeaderPath = "";

#if UNITY_EDITOR
            string[] paths = null;
#endif

            bool useStreamingAssetPath = true;
#if !UNITY_DOTSRUNTIME
            useStreamingAssetPath = SceneBundleHandle.UseAssetBundles;
#endif
            if (useStreamingAssetPath)
            {
                sceneHeaderPath = EntityScenesPaths.GetLoadPath(sceneGUID, EntityScenesPaths.PathType.EntitiesHeader, -1);
            }
            else
            {
#if UNITY_EDITOR
                AssetDatabaseCompatibility.GetArtifactPaths(artifactHash, out paths);
                sceneHeaderPath = EntityScenesPaths.GetLoadPathFromArtifactPaths(paths, EntityScenesPaths.PathType.EntitiesHeader);
#endif
            }

            EntityManager.AddComponentData(sceneEntity, new ResolvedSceneHash {
                ArtifactHash = artifactHash
            });

            var group = EntityManager.AddBuffer <LinkedEntityGroup>(sceneEntity);
            Assert.AreEqual(0, group.Length);
            group.Add(sceneEntity);

            // @TODO: AsyncReadManager currently crashes with empty path.
            //        It should be possible to remove this after that is fixed.
            if (String.IsNullOrEmpty(sceneHeaderPath))
            {
#if UNITY_EDITOR
                var scenePath = AssetDatabaseCompatibility.GuidToPath(sceneGUID);
                var logPath   = System.IO.Path.GetFullPath(System.IO.Path.Combine(UnityEngine.Application.dataPath, "../Logs"));
                Debug.LogError($"Loading Entity Scene failed because the entity header file couldn't be resolved. This might be caused by a failed import of the entity scene. Please take a look at the SubScene MonoBehaviour that references this scene or at the asset import worker log in {logPath}. scenePath={scenePath} guid={sceneGUID}");
#else
                Debug.LogError($"Loading Entity Scene failed because the entity header file couldn't be resolved: guid={sceneGUID}.");
#endif
                return(false);
            }

#if !UNITY_DOTSRUNTIME
            if (!BlobAssetReference <SceneMetaData> .TryRead(sceneHeaderPath, SceneMetaDataSerializeUtility.CurrentFileFormatVersion, out var sceneMetaDataRef))
            {
#if UNITY_EDITOR
                Debug.LogError($"Loading Entity Scene failed because the entity header file was an old version or doesn't exist: guid={sceneGUID} path={sceneHeaderPath}");
#else
                Debug.LogError($"Loading Entity Scene failed because the entity header file was an old version or doesn't exist: {sceneGUID}\nNOTE: In order to load SubScenes in the player you have to use the new BuildConfiguration asset based workflow to build & run your player.\n{sceneHeaderPath}");
#endif
                return(false);
            }
#else
            Assert.IsTrue(EntityManager.HasComponent <RequestSceneHeader>(sceneEntity), "You may only resolve a scene if the entity has a RequestSceneHeader component");
            Assert.IsTrue(EntityManager.HasComponent <SceneMetaDataLoaded>(sceneEntity), "You may only resolve a scene if the entity has a SceneMetaDataLoaded component");
            var sceneMetaDataLoaded = EntityManager.GetComponentData <SceneMetaDataLoaded>(sceneEntity);
            if (!sceneMetaDataLoaded.Success)
            {
                return(false);
            }

            var requestSceneHeader = EntityManager.GetComponentData <RequestSceneHeader>(sceneEntity);
            var sceneMetaDataRef   = default(BlobAssetReference <SceneMetaData>);
            var asyncOp            = new AsyncOp()
            {
                m_Handle = requestSceneHeader.IOHandle
            };
            using (asyncOp)
            {
                unsafe
                {
                    asyncOp.GetData(out var sceneData, out var sceneDataSize);

                    if (!BlobAssetReference <SceneMetaData> .TryRead(sceneData, SceneMetaDataSerializeUtility.CurrentFileFormatVersion, out sceneMetaDataRef))
                    {
                        Debug.LogError($"Loading Entity Scene failed because the entity header file was an old version or doesn't exist: {sceneGUID}\nNOTE: In order to load SubScenes in the player you have to use the new BuildConfiguration asset based workflow to build & run your player.\n{sceneHeaderPath}");
                        return(false);
                    }
                }
            }
#endif

            ref var sceneMetaData = ref sceneMetaDataRef.Value;