private void LoadFakeSubScene(PersistencySettings settings, Unity.Entities.Hash128 sceneGUID, int amountPerArchetype) { List <(PersistencyAuthoring, Entity)> toConvert = new List <(PersistencyAuthoring, Entity)>(); toConvert.AddRange(CreateGameObjectsAndPrimaryEntities(amountPerArchetype, false, true, true)); toConvert.AddRange(CreateGameObjectsAndPrimaryEntities(amountPerArchetype, false, false, true)); toConvert.AddRange(CreateGameObjectsAndPrimaryEntities(amountPerArchetype, true, false, true)); toConvert.AddRange(CreateGameObjectsAndPrimaryEntities(amountPerArchetype, true, false, false)); toConvert.AddRange(CreateGameObjectsAndPrimaryEntities(amountPerArchetype, false, true, false)); toConvert.AddRange(CreateGameObjectsAndPrimaryEntities(amountPerArchetype, true, true, true)); PersistencyConversionSystem.Convert(toConvert, (settings, m_Manager.CreateEntity()), m_Manager, sceneGUID); foreach ((PersistencyAuthoring, Entity)pair in toConvert) { m_Manager.AddSharedComponentData(pair.Item2, new SceneSection() { SceneGUID = sceneGUID, Section = 0 }); Object.DestroyImmediate(pair.Item1); // Destroying the gameobjects after conversion is necessary to be able to load multiple fake subscenes } // Fake the scene section entity, so the PersistentSceneSystem does it's work Entity sceneSectionEntity = m_Manager.CreateEntity(); m_Manager.AddComponentData(sceneSectionEntity, new SceneSectionData() { SceneGUID = sceneGUID, SubSectionIndex = 0, }); m_Manager.AddComponentData(sceneSectionEntity, new RequestPersistentSceneSectionLoaded()); }
void RequestAssetTargetHash(MessageEventArgs args) { //@TODO: should be based on connection / BuildSetting var buildTarget = EditorUserBuildSettings.activeBuildTarget; // Array of Asset GUIDs the player is requesting the asset hash of using (var assets = args.ReceiveArray <GUID>()) { // Set of ready to send (all valid target hashes) assets var resolvedAssets = new HashSet <ResolvedAssetID>(); foreach (var asset in assets) { LiveLinkMsg.LogReceived($"AssetBundleTargetHash request => {asset} | {AssetDatabase.GUIDToAssetPath(asset.ToString())}"); // For each Asset- queue calculating target hash and add to tracked assets Unity.Entities.Hash128 targetHash = LiveLinkBuildPipeline.CalculateTargetHash(asset, buildTarget, ImportMode.Asynchronous); m_TrackedAssets[asset] = targetHash; resolvedAssets.Add(new ResolvedAssetID { GUID = asset, TargetHash = targetHash }); // If asset hash is valid (meaning import is ready) then also do the same for dependencies if (targetHash.IsValid) { LiveLinkBuildPipeline.CalculateTargetDependencies(targetHash, buildTarget, out ResolvedAssetID[] dependencies, ImportMode.Asynchronous, asset); foreach (var dependency in dependencies) { m_TrackedAssets[dependency.GUID] = dependency.TargetHash; resolvedAssets.Add(new ResolvedAssetID { GUID = dependency.GUID, TargetHash = dependency.TargetHash }); } } } // Callback to re-send tracked assets when their targethash changes if (m_TrackedAssets.Count > 0) { TimeBasedCallbackInvoker.SetCallback(DetectChangedAssets); } // No assets? Send nothing and set no callback if (resolvedAssets.Count == 0) { return; } var resolved = new NativeArray <ResolvedAssetID>(resolvedAssets.Count, Allocator.Temp); int j = 0; foreach (var id in resolvedAssets) { resolved[j++] = id; } SendAssetTargetHash(resolved, args.playerId); } }
public void TestSceneLoad([Values(1, 2, 3, 10)] int total) { PersistencySettings settings = CreateTestSettings(); // override the settings field PersistentSceneSystem persistentSceneSystem = World.GetOrCreateSystem <PersistentSceneSystem>(); persistentSceneSystem.ReplaceSettings(settings); // Load SubScenes for (int i = 0; i < total; i++) { Unity.Entities.Hash128 sceneGUID = Hash128.Compute(i); LoadFakeSubScene(settings, sceneGUID, i + 10); } persistentSceneSystem.Update(); for (int i = 0; i < total; i++) { Unity.Entities.Hash128 sceneGUID = Hash128.Compute(i); // Since BeginFramePersistencySystem hasn't run, this data will be uninitialized. // We're only interested if it's the container exists & if it's the right size Assert.True(persistentSceneSystem.PersistentDataStorage.IsInitialized(sceneGUID), "Expected the subscene to have an initialized PersistentDataContainer"); PersistentDataContainer container = persistentSceneSystem.PersistentDataStorage.GetReadContainerForLatestWriteIndex(sceneGUID, out bool isInitial); Assert.True(isInitial); Assert.True(container.DataIdentifier == sceneGUID, $"Expected the container to have the sceneGUID {sceneGUID} as data identifier, but it was {container.DataIdentifier}."); Assert.True(container.DataLayoutCount == 6, $"LoadFakeSubScene creates 6 different types of persistable entities so we expect 6 different data layouts in the container, but it reports {container.DataLayoutCount}"); int entitiesInScene = (i + 10) * 6; int entitiesInContainer = container.CalculateEntityCapacity(); Assert.True(entitiesInContainer == entitiesInScene, $"LoadFakeSubScene created {entitiesInScene} entities, but the container reports {entitiesInContainer}."); } m_Manager.DestroyEntity(m_Manager.UniversalQuery); }
//TODO: There is too much code duplication here, refactor this to send general artifacts to the editor unsafe void SendSubScene(Unity.Entities.Hash128 subSceneGuid, Unity.Entities.Hash128 buildSettingsGuid, int playerId) { LiveLinkMsg.LogInfo($"Sending SubScene: 'GUID: {subSceneGuid}' with 'BuildSettings: {buildSettingsGuid}' to playerId: {playerId}"); var hash = EntityScenesPaths.GetSubSceneArtifactHash(subSceneGuid, buildSettingsGuid, AssetDatabaseExperimental.ImportSyncMode.Block); AssetDatabaseExperimental.GetArtifactPaths(hash, out var paths); var sceneHeaderPath = EntityScenesPaths.GetLoadPathFromArtifactPaths(paths, EntityScenesPaths.PathType.EntitiesHeader); if (!File.Exists(sceneHeaderPath)) { Debug.LogError("Send Entity Scene failed because the entity header file could not be found: " + sceneHeaderPath); return; } if (!BlobAssetReference <SceneMetaData> .TryRead(sceneHeaderPath, SceneMetaDataSerializeUtility.CurrentFileFormatVersion, out var sceneMetaDataRef)) { Debug.LogError("Send Entity Scene failed because the entity header file was an old version: " + sceneHeaderPath); return; } ref var sceneMetaData = ref sceneMetaDataRef.Value;
static string ResolveCachePath(Unity.Entities.Hash128 targethash) { var path = "Library/LiveLinkAssetBundleCache/" + targethash; return(path); }
public void TestPersistAndApply([Values(1, 2, 3, 10)] int total, [Values(false, true)] bool groupedJobs) { PersistencySettings settings = CreateTestSettings(); settings.ForceUseGroupedJobsInEditor = groupedJobs; settings.ForceUseNonGroupedJobsInBuild = !groupedJobs; Assert.True(groupedJobs == settings.UseGroupedJobs()); // Override the settings fields of both systems PersistentSceneSystem persistentSceneSystem = World.GetOrCreateSystem <PersistentSceneSystem>(); persistentSceneSystem.ReplaceSettings(settings); BeginFramePersistencySystem beginFramePersistencySystem = World.GetOrCreateSystem <BeginFramePersistencySystem>(); beginFramePersistencySystem.ReplaceSettings(settings); EndInitializationEntityCommandBufferSystem ecbSystem = World.GetOrCreateSystem <EndInitializationEntityCommandBufferSystem>(); // Load SubScenes for (int i = 0; i < total; i++) { Unity.Entities.Hash128 sceneGUID = Hash128.Compute(i); LoadFakeSubScene(settings, sceneGUID, i + 10); } // The fake subscene entities don't have any actual test data on them yet, so add some here Entities.ForEach((Entity e, ref PersistenceState persistenceState) => { // tracking add/remove of bufferdata isn't supported so we add all of them DynamicBuffer <DynamicBufferData1> buffer1 = m_Manager.AddBuffer <DynamicBufferData1>(e); buffer1.Add(new DynamicBufferData1() { Value = persistenceState.ArrayIndex }); DynamicBuffer <DynamicBufferData2> buffer2 = m_Manager.AddBuffer <DynamicBufferData2>(e); buffer2.Add(new DynamicBufferData2() { Value = persistenceState.ArrayIndex }); DynamicBuffer <DynamicBufferData3> buffer3 = m_Manager.AddBuffer <DynamicBufferData3>(e); buffer3.Add(new DynamicBufferData3() { Value = (byte)persistenceState.ArrayIndex }); // Add different components if (persistenceState.ArrayIndex % 2 == 0) { m_Manager.AddComponentData(e, new EcsTestData(persistenceState.ArrayIndex)); } else { m_Manager.AddComponent <EmptyEcsTestData>(e); } }); persistentSceneSystem.Update(); beginFramePersistencySystem.Update(); ecbSystem.Update(); // Check if some data was written to the container for (int i = 0; i < total; i++) { Unity.Entities.Hash128 sceneGUID = Hash128.Compute(i); Assert.True(persistentSceneSystem.PersistentDataStorage.IsInitialized(sceneGUID), "Expected the subscene to have an initialized PersistentDataContainer"); PersistentDataContainer container = persistentSceneSystem.PersistentDataStorage.GetReadContainerForLatestWriteIndex(sceneGUID, out bool isInitial); Assert.True(isInitial); bool hasOnlyZero = true; foreach (byte dataByte in container.GetRawData()) { if (dataByte != 0) { hasOnlyZero = false; break; } } Assert.False(hasOnlyZero, ""); } // Change entities Entities.ForEach((Entity e, ref PersistenceState persistenceState) => { DynamicBuffer <DynamicBufferData1> buffer1 = m_Manager.GetBuffer <DynamicBufferData1>(e); buffer1[0] = default; DynamicBuffer <DynamicBufferData2> buffer2 = m_Manager.GetBuffer <DynamicBufferData2>(e); buffer2[0] = default; DynamicBuffer <DynamicBufferData3> buffer3 = m_Manager.GetBuffer <DynamicBufferData3>(e); buffer3[0] = default; if (persistenceState.ArrayIndex % 2 == 0) { m_Manager.RemoveComponent <EcsTestData>(e); m_Manager.AddComponent <EmptyEcsTestData>(e); } else { m_Manager.AddComponentData(e, new EcsTestData(persistenceState.ArrayIndex)); m_Manager.RemoveComponent <EmptyEcsTestData>(e); } }); // Revert entities to initial state for (int i = 0; i < total; i++) { Unity.Entities.Hash128 sceneGUID = Hash128.Compute(i); Assert.True(persistentSceneSystem.PersistentDataStorage.IsInitialized(sceneGUID), "Expected the subscene to have an initialized PersistentDataContainer"); PersistentDataContainer container = persistentSceneSystem.PersistentDataStorage.GetReadContainerForLatestWriteIndex(sceneGUID, out bool isInitial); Assert.True(isInitial); beginFramePersistencySystem.RequestApply(container); } beginFramePersistencySystem.Update(); ecbSystem.Update(); // Test if the revert actually worked on entities that were tracking the components Entities.ForEach((Entity e, ref PersistenceState persistenceState) => { if (m_Manager.GetName(e).Contains("_B")) // this means it was tracking all buffer components { DynamicBuffer <DynamicBufferData1> buffer1 = m_Manager.GetBuffer <DynamicBufferData1>(e); Assert.True(buffer1[0].Value == persistenceState.ArrayIndex, "The entity was expected to be reset and have it's original buffer value (1)"); DynamicBuffer <DynamicBufferData2> buffer2 = m_Manager.GetBuffer <DynamicBufferData2>(e); Assert.True(Math.Abs(buffer2[0].Value - persistenceState.ArrayIndex) < 0.001f, "The entity was expected to be reset and have it's original buffer value (2)"); DynamicBuffer <DynamicBufferData3> buffer3 = m_Manager.GetBuffer <DynamicBufferData3>(e); Assert.True(buffer3[0].Value == (byte)persistenceState.ArrayIndex, "The entity was expected to be reset and have it's original buffer value (3)"); } else { DynamicBuffer <DynamicBufferData1> buffer1 = m_Manager.GetBuffer <DynamicBufferData1>(e); Assert.True(buffer1[0].Value == 0, "The entity was expected to NOT be reset and have a 0 buffer value. (1)"); DynamicBuffer <DynamicBufferData2> buffer2 = m_Manager.GetBuffer <DynamicBufferData2>(e); Assert.True(buffer2[0].Value == 0, "The entity was expected to NOT be reset and have a 0 buffer value. (2)"); DynamicBuffer <DynamicBufferData3> buffer3 = m_Manager.GetBuffer <DynamicBufferData3>(e); Assert.True(buffer3[0].Value == 0, "The entity was expected to NOT be reset and have a 0 buffer value. (3)"); } if (persistenceState.ArrayIndex % 2 == 0) { if (m_Manager.GetName(e).Contains("_C")) // this means it was tracking all standard components { Assert.True(m_Manager.HasComponent <EcsTestData>(e), "The entity was expected to be reset and have its original component back."); } else { Assert.False(m_Manager.HasComponent <EcsTestData>(e), "The entity was expected to NOT be reset and NOT have its original component back."); } if (m_Manager.GetName(e).Contains("_T")) // this means it was tracking all tag components { Assert.False(m_Manager.HasComponent <EmptyEcsTestData>(e), "The entity was expected to be reset and have the new TAG component removed."); } else { Assert.True(m_Manager.HasComponent <EmptyEcsTestData>(e), "The entity was expected to NOT be reset and NOT have the new TAG component removed. "); } } else { if (m_Manager.GetName(e).Contains("_C")) // this means it was tracking all standard components { Assert.False(m_Manager.HasComponent <EcsTestData>(e), "The entity was expected to be reset and have the new component removed."); } else { Assert.True(m_Manager.HasComponent <EcsTestData>(e), "The entity was expected to NOT be reset and NOT have the new component removed."); } if (m_Manager.GetName(e).Contains("_T")) // this means it was tracking all tag components { Assert.True(m_Manager.HasComponent <EmptyEcsTestData>(e), "The entity was expected to be reset and have its original TAG component back."); } else { Assert.False(m_Manager.HasComponent <EmptyEcsTestData>(e), "The entity was expected to NOT be reset and NOT have its original TAG component back."); } } }); m_Manager.DestroyEntity(m_Manager.UniversalQuery); }