protected override JobHandle OnUpdate(JobHandle inputDeps) { var commandBuffer = _commandBufferSystem.CreateCommandBuffer().ToConcurrent(); var updateJob = new UpdateJob { attackTemplate = _enemyAttack, movementTemplate = _enemyMovement, entityType = GetArchetypeChunkEntityType(), raycastResultStateType = GetArchetypeChunkComponentType <RaycastResultState>(false), raycastResultType = GetArchetypeChunkComponentType <RaycastResult>(true), movementType = GetArchetypeChunkComponentType <Movement>(true), attackType = GetArchetypeChunkComponentType <EnemyAttack>(true), targetType = GetArchetypeChunkComponentType <TargetOwnership>(false), commands = commandBuffer }; var cleanupJob = new CleanupJob { commands = commandBuffer }; inputDeps = updateJob.Schedule(_updateQuery, inputDeps); inputDeps = updateJob.Schedule(_updateQueryNoState, inputDeps); inputDeps = cleanupJob.Schedule(_cleanupQuery, inputDeps); _commandBufferSystem.AddJobHandleForProducer(inputDeps); return(inputDeps); }
protected override JobHandle OnUpdate(JobHandle inputDependencies) { var commandBuffer = _bufferSystem.CreateCommandBuffer().ToConcurrent(); //Create New Maps var createJob = Entities.WithAll <WorldMapViewData>().WithNone <WorldMapViewSystemData>().ForEach((int nativeThreadIndex, Entity entity) => { commandBuffer.AddComponent(nativeThreadIndex, entity, new WorldMapViewSystemData()); }).Schedule(inputDependencies); _bufferSystem.AddJobHandleForProducer(createJob); //Clean Up Destroyed Maps var destroyJob = Entities.WithAll <WorldMapViewSystemData>().WithNone <WorldMapViewData>().ForEach((int nativeThreadIndex, Entity entity) => { //Cleanup Destroyed Maps commandBuffer.RemoveComponent <WorldMapViewSystemData>(nativeThreadIndex, entity); }).Schedule(createJob); _bufferSystem.AddJobHandleForProducer(destroyJob); var tileArchetype = _tileArchetype; var cleanupJob = new CleanupJob { commandBuffer = _bufferSystem.CreateCommandBuffer().ToConcurrent(), mapViews = worldMapViewDataQuery.ToComponentDataArray <WorldMapViewData>(Allocator.TempJob) }; var cleanupJobHandle = cleanupJob.Schedule(worldMapTiles, destroyJob); _bufferSystem.AddJobHandleForProducer(cleanupJobHandle); var spawnJob = new SpawnJob() { CommandBuffer = _bufferSystem.CreateCommandBuffer().ToConcurrent(), OutOfViewTiles = outOfViewQuery.ToEntityArray(Allocator.TempJob), TileArchetype = tileArchetype }.Schedule(viewChangedQuery, cleanupJobHandle); _bufferSystem.AddJobHandleForProducer(spawnJob); return(spawnJob); }
protected override JobHandle OnUpdate(JobHandle inputDeps) { m_SerialSpawnChunks.Clear(); // Make sure the list of connections and connection state is up to date var connections = connectionGroup.ToEntityArray(Allocator.TempJob); var existing = new NativeHashMap <Entity, int>(connections.Length, Allocator.Temp); for (int i = 0; i < connections.Length; ++i) { existing.TryAdd(connections[i], 1); int stateIndex; if (!m_ConnectionStateLookup.TryGetValue(connections[i], out stateIndex)) { m_ConnectionStates.Add(new ConnectionStateData { Entity = connections[i], SerializationState = new NativeHashMap <ArchetypeChunk, SerializationState>(1024, Allocator.Persistent) }); m_ConnectionStateLookup.TryAdd(connections[i], m_ConnectionStates.Count - 1); } } connections.Dispose(); for (int i = 0; i < m_ConnectionStates.Count; ++i) { int val; if (!existing.TryGetValue(m_ConnectionStates[i].Entity, out val)) { m_ConnectionStateLookup.Remove(m_ConnectionStates[i].Entity); m_ConnectionStates[i].Dispose(); if (i != m_ConnectionStates.Count - 1) { m_ConnectionStates[i] = m_ConnectionStates[m_ConnectionStates.Count - 1]; m_ConnectionStateLookup.Remove(m_ConnectionStates[i].Entity); m_ConnectionStateLookup.TryAdd(m_ConnectionStates[i].Entity, i); } m_ConnectionStates.RemoveAt(m_ConnectionStates.Count - 1); } } // Find the latest tick which has been acknowledged by all clients and cleanup all ghosts destroyed ebfore that uint currentTick = m_ServerSimulation.ServerTick; var ackedByAll = new NativeArray <uint>(1, Allocator.TempJob); ackedByAll[0] = currentTick; var findAckJob = new FindAckedByAllJob { tick = ackedByAll }; inputDeps = findAckJob.ScheduleSingle(this, inputDeps); EntityCommandBuffer commandBuffer = m_Barrier.CreateCommandBuffer(); var ghostCleanupJob = new CleanupGhostJob { currentTick = currentTick, tick = ackedByAll, commandBuffer = commandBuffer.ToConcurrent(), freeGhostIds = m_FreeGhostIds.AsParallelWriter(), ghostStateType = ComponentType.ReadWrite <GhostSystemStateComponent>() }; inputDeps = ghostCleanupJob.Schedule(this, inputDeps); var entityType = GetArchetypeChunkEntityType(); var ghostSystemStateType = GetArchetypeChunkComponentType <GhostSystemStateComponent>(); serializers.BeginSerialize(this); // Extract all newly spawned ghosts and set their ghost ids JobHandle spawnChunkHandle; var spawnChunks = ghostSpawnGroup.CreateArchetypeChunkArray(Allocator.TempJob, out spawnChunkHandle); var spawnJob = new SpawnGhostJob { spawnChunks = spawnChunks, serialSpawnChunks = m_SerialSpawnChunks, entityType = entityType, serializers = serializers, freeGhostIds = m_FreeGhostIds, allocatedGhostIds = m_AllocatedGhostIds, commandBuffer = commandBuffer }; inputDeps = spawnJob.Schedule(JobHandle.CombineDependencies(inputDeps, spawnChunkHandle)); // This was the last job using the commandBuffer m_Barrier.AddJobHandleForProducer(inputDeps); JobHandle despawnChunksHandle, ghostChunksHandle; var despawnChunks = ghostDespawnGroup.CreateArchetypeChunkArray(Allocator.TempJob, out despawnChunksHandle); var ghostChunks = ghostGroup.CreateArchetypeChunkArray(Allocator.TempJob, out ghostChunksHandle); inputDeps = JobHandle.CombineDependencies(inputDeps, despawnChunksHandle, ghostChunksHandle); var serialDep = new NativeArray <JobHandle>(m_ConnectionStates.Count + 1, Allocator.Temp); // In case there are 0 connections serialDep[0] = inputDeps; for (int con = 0; con < m_ConnectionStates.Count; ++con) { var connectionEntity = m_ConnectionStates[con].Entity; var chunkSerializationData = m_ConnectionStates[con].SerializationState; var serializeJob = new SerializeJob { driver = m_ReceiveSystem.ConcurrentDriver, unreliablePipeline = m_ReceiveSystem.UnreliablePipeline, despawnChunks = despawnChunks, ghostChunks = ghostChunks, connectionEntity = connectionEntity, chunkSerializationData = chunkSerializationData, ackFromEntity = GetComponentDataFromEntity <NetworkSnapshotAckComponent>(true), connectionFromEntity = GetComponentDataFromEntity <NetworkStreamConnection>(true), serialSpawnChunks = m_SerialSpawnChunks, entityType = entityType, ghostSystemStateType = ghostSystemStateType, serializers = serializers, compressionModel = m_CompressionModel, currentTick = currentTick, localTime = NetworkTimeSystem.TimestampMS }; // FIXME: disable safety for BufferFromEntity is not working serialDep[con + 1] = serializeJob.Schedule(serialDep[con]); } inputDeps = JobHandle.CombineDependencies(serialDep); var cleanupJob = new CleanupJob { despawnChunks = despawnChunks, spawnChunks = spawnChunks, ghostChunks = ghostChunks, serialSpawnChunks = m_SerialSpawnChunks }; inputDeps = cleanupJob.Schedule(inputDeps); return(inputDeps); }
protected override JobHandle OnUpdate(JobHandle inputDeps) { if (units.entities.Length == 0) { return(inputDeps); } Profiler.BeginSample("Explosion wait"); spellSystem.CombinedExplosionHandle.Complete(); // TODO try to remove this Profiler.EndSample(); inputDeps.Complete(); Profiler.BeginSample("Spawn "); if (!deathQueue.IsCreated) { deathQueue = new NativeQueue <Entity>(Allocator.Persistent); } if (!createdArrows.IsCreated) { createdArrows = new NativeQueue <ArrowData>(Allocator.Persistent); } while (createdArrows.Count > 0) { var data = createdArrows.Dequeue(); Spawner.Instance.SpawnArrow(data); } UpdateInjectedComponentGroups(); var cleanupJob = new CleanupJob { deathQueue = deathQueue, minionData = units.data, entitites = units.entities }; var moveUnitsJob = new MoveUnitsBelowGround() { dyingUnitData = dyingUnits.dyingData, transforms = dyingUnits.transforms, time = Time.time }; var cleanupJobFence = cleanupJob.Schedule(units.Length, SimulationState.BigBatchSize, inputDeps); var moveUnitsBelowGroundFence = moveUnitsJob.Schedule(dyingUnits.Length, SimulationState.HugeBatchSize, spellSystem.CombinedExplosionHandle); Profiler.EndSample(); cleanupJobFence.Complete(); moveUnitsBelowGroundFence.Complete(); Profiler.BeginSample("LifeCycleManager - Main Thread"); float time = Time.time; if (dyingUnits.Length > 0) { for (int i = 0; i < dyingUnits.Length; i++) { if (time > dyingUnits.dyingData[i].TimeAtWhichToExpire) { var entityToKill = dyingUnits.entities[i]; queueForKillingEntities.Enqueue(entityToKill); } //else if (time > dyingData[i].TimeAtWhichToExpire - 2f) //{ // float t = (dyingData[i].TimeAtWhichToExpire - time) / 2f; // var transform = transforms[i]; // transform.Position.y = math.lerp(dyingData[i].StartingYCoord, dyingData[i].StartingYCoord - 1f, t); // transforms[i] = transform; //} } } if (dyingArrows.Length > 0) { for (int i = 0; i < dyingArrows.Length; i++) { if (time > dyingArrows.dyingData[i].TimeAtWhichToExpire) { var arrowToKill = dyingArrows.entities[i]; queueForKillingEntities.Enqueue(arrowToKill); } } } Profiler.EndSample(); Profiler.BeginSample("Queue processing"); float timeForUnitExpiring = Time.time + 5f; float timeForArrowExpiring = Time.time + 1f; Profiler.BeginSample("Death queue"); int processed = 0; while (deathQueue.Count > 0) { var entityToKill = deathQueue.Dequeue(); if (EntityManager.HasComponent <MinionData>(entityToKill)) { EntityManager.RemoveComponent <MinionData>(entityToKill); entitiesThatNeedToBeKilled.Enqueue(entityToKill); } if (EntityManager.HasComponent <ArrowData>(entityToKill)) { EntityManager.AddComponentData(entityToKill, new DyingUnitData(timeForArrowExpiring, 0)); } } Profiler.EndSample(); Profiler.BeginSample("Explosion wait"); spellSystem.CombinedExplosionHandle.Complete(); Profiler.EndSample(); Profiler.BeginSample("Killing minionEntities"); // TODO try batched replacing while (entitiesThatNeedToBeKilled.Count > 0 && processed < MaxDyingUnitsPerFrame) { processed++; var entityToKill = entitiesThatNeedToBeKilled.Dequeue(); if (EntityManager.HasComponent <MinionTarget>(entityToKill)) { EntityManager.RemoveComponent <MinionTarget>(entityToKill); if (EntityManager.HasComponent <AliveMinionData>(entityToKill)) { EntityManager.RemoveComponent <AliveMinionData>(entityToKill); } var textureAnimatorData = EntityManager.GetComponentData <TextureAnimatorData>(entityToKill); textureAnimatorData.NewAnimationId = AnimationName.Death; var transform = EntityManager.GetComponentData <UnitTransformData>(entityToKill); EntityManager.AddComponentData(entityToKill, new DyingUnitData(timeForUnitExpiring, transform.Position.y)); EntityManager.SetComponentData(entityToKill, textureAnimatorData); var formations = GetComponentDataFromEntity <FormationData>(); var formation = formations[transform.FormationEntity]; formation.UnitCount--; formation.Width = (int)math.ceil((math.sqrt(formation.UnitCount / 2f) * 2f)); if (formation.UnitCount == 0) { formation.FormationState = FormationData.State.AllDead; } formations[transform.FormationEntity] = formation; } } Profiler.EndSample(); processed = 0; Profiler.BeginSample("Flying queue"); while (entitiesForFlying.Count > 0 && processed < MaxDyingUnitsPerFrame) { processed++; var entity = entitiesForFlying.Dequeue(); if (EntityManager.Exists(entity) && !EntityManager.HasComponent <FlyingData>(entity)) { if (EntityManager.HasComponent(entity, typeof(AliveMinionData))) { EntityManager.RemoveComponent <AliveMinionData>(entity); } EntityManager.AddComponentData(entity, new FlyingData()); } } Profiler.EndSample(); Profiler.BeginSample("Destroying entities"); while (queueForKillingEntities.Count > 0) { EntityManager.DestroyEntity(queueForKillingEntities.Dequeue()); } Profiler.EndSample(); Profiler.EndSample(); return(new JobHandle()); }