static void ApplyBlobAssetChanges( EntityManager entityManager, NativeArray <EntityGuid> packedEntityGuids, NativeMultiHashMap <int, Entity> packedEntities, NativeArray <ComponentType> packedTypes, NativeArray <BlobAssetChange> createdBlobAssets, NativeArray <byte> createdBlobAssetData, NativeArray <ulong> destroyedBlobAssets, NativeArray <BlobAssetReferenceChange> blobAssetReferenceChanges) { if (createdBlobAssets.Length == 0 && blobAssetReferenceChanges.Length == 0) { return; } s_ApplyBlobAssetChangesProfilerMarker.Begin(); var managedObjectBlobAssetReferencePatches = new NativeMultiHashMap <EntityComponentPair, ManagedObjectBlobAssetReferencePatch>(blobAssetReferenceChanges.Length, Allocator.Temp); var patcherBlobAssetSystem = entityManager.World.GetOrCreateSystem <EntityPatcherBlobAssetSystem>(); var blobAssetDataPtr = (byte *)createdBlobAssetData.GetUnsafePtr(); for (var i = 0; i < createdBlobAssets.Length; i++) { if (!patcherBlobAssetSystem.TryGetBlobAsset(createdBlobAssets[i].Hash, out _)) { patcherBlobAssetSystem.AllocateBlobAsset(blobAssetDataPtr, createdBlobAssets[i].Length, createdBlobAssets[i].Hash); } blobAssetDataPtr += createdBlobAssets[i].Length; } for (var i = 0; i < destroyedBlobAssets.Length; i++) { patcherBlobAssetSystem.ReleaseBlobAsset(entityManager, destroyedBlobAssets[i]); } for (var i = 0; i < blobAssetReferenceChanges.Length; i++) { var packedComponent = blobAssetReferenceChanges[i].Component; var component = packedTypes[packedComponent.PackedTypeIndex]; var targetOffset = blobAssetReferenceChanges[i].Offset; BlobAssetReferenceData targetBlobAssetReferenceData; if (patcherBlobAssetSystem.TryGetBlobAsset(blobAssetReferenceChanges[i].Value, out var blobAssetPtr)) { targetBlobAssetReferenceData = new BlobAssetReferenceData { m_Ptr = (byte *)blobAssetPtr.Data }; } if (packedEntities.TryGetFirstValue(packedComponent.PackedEntityIndex, out var entity, out var iterator)) { do { if (!entityManager.Exists(entity)) { Debug.LogWarning($"ApplyBlobAssetReferencePatches<{component}>({packedEntityGuids[packedComponent.PackedEntityIndex]}) but entity to patch does not exist."); } else if (!entityManager.HasComponent(entity, component)) { Debug.LogWarning($"ApplyBlobAssetReferencePatches<{component}>({packedEntityGuids[packedComponent.PackedEntityIndex]}) but component in entity to patch does not exist."); } else { if (component.IsBuffer) { var pointer = (byte *)entityManager.GetBufferRawRW(entity, component.TypeIndex); UnsafeUtility.MemCpy(pointer + targetOffset, &targetBlobAssetReferenceData, sizeof(BlobAssetReferenceData)); } else if (component.IsManagedComponent || component.IsSharedComponent) { managedObjectBlobAssetReferencePatches.Add( new EntityComponentPair { Entity = entity, Component = component }, new ManagedObjectBlobAssetReferencePatch { Id = targetOffset, Target = blobAssetReferenceChanges[i].Value }); } else { var pointer = (byte *)entityManager.GetComponentDataRawRW(entity, component.TypeIndex); UnsafeUtility.MemCpy(pointer + targetOffset, &targetBlobAssetReferenceData, sizeof(BlobAssetReferenceData)); } } }while (packedEntities.TryGetNextValue(out entity, ref iterator)); } } s_ApplyBlobAssetChangesProfilerMarker.End(); #if !UNITY_DOTSRUNTIME var managedObjectPatcher = new ManagedObjectBlobAssetReferencePatcher(patcherBlobAssetSystem); // Apply all managed entity patches using (var keys = managedObjectBlobAssetReferencePatches.GetKeyArray(Allocator.Temp)) { keys.Sort(); var uniqueCount = keys.Unique(); for (var i = 0; i < uniqueCount; i++) { var pair = keys[i]; var patches = managedObjectBlobAssetReferencePatches.GetValuesForKey(pair); if (pair.Component.IsManagedComponent) { var obj = entityManager.GetComponentObject <object>(pair.Entity, pair.Component); managedObjectPatcher.ApplyPatches(ref obj, patches); } else if (pair.Component.IsSharedComponent) { var obj = entityManager.GetSharedComponentData(pair.Entity, pair.Component.TypeIndex); managedObjectPatcher.ApplyPatches(ref obj, patches); entityManager.SetSharedComponentDataBoxedDefaultMustBeNull(pair.Entity, pair.Component.TypeIndex, obj); } patches.Dispose(); } } #endif managedObjectBlobAssetReferencePatches.Dispose(); // Workaround to catch some special cases where the memory is never released. (e.g. reloading a scene, toggling live-link on/off). patcherBlobAssetSystem.ReleaseUnusedBlobAssets(); }
protected override void Consume() { NativeMultiHashMap <Entity, Effect2Context> effects = _effects; Entities.WithReadOnly(effects).ForEach((ref Entity entity, ref Health health, ref Armor armor) => { NativeMultiHashMap <Entity, Effect2Context> .Enumerator effectEnumerator = effects.GetValuesForKey(entity); Health hp = health; while (effectEnumerator.MoveNext()) { hp.Value -= effectEnumerator.Current.AttackPower * effectEnumerator.Current.Effect.Value / armor.Value; } health = hp; }).WithBurst() .ScheduleParallel(); }