using Unity.Collections; using Unity.Entities; using static Unity.Entities.SystemAPI; using Unity.MegaCity.Audio; namespace Unity.MegaCity.Authoring { /// /// The system gets all ECSoundEmitterComponent which belongs to the buildings. /// Then builds a hashmap based on the [definitionIndex] as a key and insert a new SingleEmitterData as a value. /// By using the hashmap build an AudioBlobRef data and add that to the Scene. /// Each Scene has a AudioBlobRef with a map of every single emitter. /// [WorldSystemFilter(WorldSystemFilterFlags.BakingSystem)] [UpdateInGroup(typeof(PostBakingSystemGroup))] [BakingVersion("julian", 2)] public partial struct SoundEmitterBlobBakingSystem : ISystem { private EntityQuery m_SoundEmitterQuery; public void OnCreate(ref SystemState state) { m_SoundEmitterQuery = state.GetEntityQuery(typeof(SoundEmitter)); } public void OnUpdate(ref SystemState state) { using var blobBuilder = new BlobBuilder(Allocator.Temp); var entityCount = m_SoundEmitterQuery.CalculateEntityCount(); var highestIndex = 0; var rootSceneEntity = Entity.Null; var hashMap = new NativeParallelMultiHashMap(entityCount, Allocator.Temp); foreach (var (soundEmitter, entity) in Query().WithEntityAccess()) { if (rootSceneEntity == Entity.Null) { //The first entity of the scene is used to store the AudioBlobRef [Blob Asset] //This is necessary per scene to keep one asset per scene since each scene is streamed (load/unload) rootSceneEntity = entity; } var definitionIndex = soundEmitter.definitionIndex < 0 ? 0 : soundEmitter.definitionIndex; var emitterData = new SingleEmitterData { Position = soundEmitter.position, Direction = soundEmitter.direction, }; hashMap.Add(definitionIndex, emitterData); if (definitionIndex > highestIndex) highestIndex = definitionIndex; } // Don't create audio blob assets for sub-scenes with no ECSoundEmitterComponent if (rootSceneEntity == Entity.Null) return; ref var allEmitterData = ref blobBuilder.ConstructRoot(); var defInxBegBuilder = blobBuilder.Allocate(ref allEmitterData.DefIndexBeg, highestIndex + 1); var defInxEndBuilder = blobBuilder.Allocate(ref allEmitterData.DefIndexEnd, highestIndex + 1); var emitterBuilder = blobBuilder.Allocate(ref allEmitterData.Emitters, entityCount); int emitterIndex = 0; for (int definitionIndex = 0; definitionIndex < highestIndex; definitionIndex++) { defInxBegBuilder[definitionIndex] = emitterIndex; var enumerator = hashMap.GetValuesForKey(definitionIndex); while (enumerator.MoveNext()) { emitterBuilder[emitterIndex] = enumerator.Current; emitterIndex++; } defInxEndBuilder[definitionIndex] = emitterIndex; } var blobRef = blobBuilder.CreateBlobAssetReference(Allocator.Persistent); state.EntityManager.AddComponentData(rootSceneEntity, new AudioBlobRef { Data = blobRef }); } } }