protected override unsafe void OnUpdate() { EntityCommandBuffer commandBuffer = m_BeginSimulationBarrier.CreateCommandBuffer(); var spawnListEntity = GetSingletonEntity <PredictedGhostSpawnList>(); var spawnListFromEntity = GetBufferFromEntity <PredictedGhostSpawn>(); if (!m_GhostInitQuery.IsEmptyIgnoreFilter) { m_ChildEntityLookup.Clear(); var childCount = m_ChildEntityQuery.CalculateEntityCountWithoutFiltering(); if (childCount > m_ChildEntityLookup.Capacity) { m_ChildEntityLookup.Capacity = childCount; } var buildChildJob = new BuildChildEntityLookupJob { entityType = GetEntityTypeHandle(), childEntityLookup = m_ChildEntityLookup.AsParallelWriter() }; Dependency = buildChildJob.ScheduleParallel(m_ChildEntityQuery, Dependency); var initJob = new InitGhostJob { GhostComponentCollection = m_GhostCollectionSystem.m_GhostComponentCollection, GhostTypeCollection = m_GhostCollectionSystem.m_GhostTypeCollection, GhostComponentIndex = m_GhostCollectionSystem.m_GhostComponentIndex, entityType = GetEntityTypeHandle(), snapshotDataType = GetComponentTypeHandle <SnapshotData>(), snapshotDataBufferType = GetBufferTypeHandle <SnapshotDataBuffer>(), spawnListFromEntity = spawnListFromEntity, spawnListEntity = spawnListEntity, ghostFromEntity = GetComponentDataFromEntity <GhostComponent>(), ghostTypeFromEntity = GetComponentDataFromEntity <GhostTypeComponent>(true), ghostPrefabBufferFromEntity = GetBufferFromEntity <GhostPrefabBuffer>(true), prefabEntity = GetSingletonEntity <GhostPrefabCollectionComponent>(), commandBuffer = commandBuffer, spawnTick = m_SpawnTick, linkedEntityGroupType = GetBufferTypeHandle <LinkedEntityGroup>(), childEntityLookup = m_ChildEntityLookup }; var listLength = m_GhostCollectionSystem.m_GhostComponentCollection.Length; if (listLength <= 32) { var dynamicListJob = new InitGhostJob32 { Job = initJob }; DynamicTypeList.PopulateList(this, m_GhostCollectionSystem.m_GhostComponentCollection, true, ref dynamicListJob.List); Dependency = dynamicListJob.ScheduleSingle(m_GhostInitQuery, Dependency); } else if (listLength <= 64) { var dynamicListJob = new InitGhostJob64 { Job = initJob }; DynamicTypeList.PopulateList(this, m_GhostCollectionSystem.m_GhostComponentCollection, true, ref dynamicListJob.List); Dependency = dynamicListJob.ScheduleSingle(m_GhostInitQuery, Dependency); } else if (listLength <= 128) { var dynamicListJob = new InitGhostJob128 { Job = initJob }; DynamicTypeList.PopulateList(this, m_GhostCollectionSystem.m_GhostComponentCollection, true, ref dynamicListJob.List); Dependency = dynamicListJob.ScheduleSingle(m_GhostInitQuery, Dependency); } else { throw new System.InvalidOperationException( $"Too many ghost component types present in project, limit is {DynamicTypeList.MaxCapacity} types. This is any struct which has a field marked with GhostField attribute."); } } // Validate all ghosts in the list of predictive spawn ghosts and destroy the ones which are too old uint interpolatedTick = m_ClientSimulationSystemGroup.InterpolationTick; Dependency = Job.WithCode(() => { var spawnList = spawnListFromEntity[spawnListEntity]; for (int i = 0; i < spawnList.Length; ++i) { var ghost = spawnList[i]; if (SequenceHelpers.IsNewer(interpolatedTick, ghost.spawnTick)) { // Destroy entity and remove from list commandBuffer.DestroyEntity(ghost.entity); spawnList[i] = spawnList[spawnList.Length - 1]; spawnList.RemoveAt(spawnList.Length - 1); --i; } } }).Schedule(Dependency); m_BeginSimulationBarrier.AddJobHandleForProducer(Dependency); m_SpawnTick = m_ClientSimulationSystemGroup.ServerTick; }
protected override void OnUpdate() { if (!m_GhostCollectionSystem.m_GhostTypeCollection.IsCreated) { return; } if (m_GhostPredictionSystemGroup.PredictingTick != m_GhostPredictionHistorySystem.LastBackupTick) { return; } m_ChildEntityLookup.Clear(); var childCount = m_ChildEntityQuery.CalculateEntityCountWithoutFiltering(); if (childCount > m_ChildEntityLookup.Capacity) { m_ChildEntityLookup.Capacity = childCount; } var buildChildJob = new BuildChildEntityLookupJob { entityType = GetEntityTypeHandle(), childEntityLookup = m_ChildEntityLookup.AsParallelWriter() }; Dependency = buildChildJob.ScheduleParallel(m_ChildEntityQuery, Dependency); var smoothingJob = new PredictionSmoothingJob { predictionState = m_GhostPredictionHistorySystem.PredictionState, ghostType = GetComponentTypeHandle <GhostComponent>(true), predictedGhostType = GetComponentTypeHandle <PredictedGhostComponent>(true), entityType = GetEntityTypeHandle(), GhostComponentCollection = m_GhostCollectionSystem.m_GhostComponentCollection, GhostTypeCollection = m_GhostCollectionSystem.m_GhostTypeCollection, GhostComponentIndex = m_GhostCollectionSystem.m_GhostComponentIndex, childEntityLookup = m_ChildEntityLookup, linkedEntityGroupType = GetBufferTypeHandle <LinkedEntityGroup>(), tick = m_GhostPredictionSystemGroup.PredictingTick, translationType = ComponentType.ReadWrite <Translation>() }; Dependency = JobHandle.CombineDependencies(Dependency, m_GhostPredictionHistorySystem.PredictionStateWriteJobHandle); var listLength = m_GhostCollectionSystem.m_GhostComponentCollection.Length; if (listLength <= 32) { var dynamicListJob = new PredictionSmoothingJob32 { Job = smoothingJob }; DynamicTypeList.PopulateList(this, m_GhostCollectionSystem.m_GhostComponentCollection, true, ref dynamicListJob.List); Dependency = dynamicListJob.ScheduleParallel(m_PredictionQuery, Dependency); } else if (listLength <= 64) { var dynamicListJob = new PredictionSmoothingJob64 { Job = smoothingJob }; DynamicTypeList.PopulateList(this, m_GhostCollectionSystem.m_GhostComponentCollection, true, ref dynamicListJob.List); Dependency = dynamicListJob.ScheduleParallel(m_PredictionQuery, Dependency); } else if (listLength <= 128) { var dynamicListJob = new PredictionSmoothingJob128 { Job = smoothingJob }; DynamicTypeList.PopulateList(this, m_GhostCollectionSystem.m_GhostComponentCollection, true, ref dynamicListJob.List); Dependency = dynamicListJob.ScheduleParallel(m_PredictionQuery, Dependency); } else { throw new System.InvalidOperationException( $"Too many ghost component types present in project, limit is {DynamicTypeList.MaxCapacity} types. This is any struct which has a field marked with GhostField attribute."); } m_GhostPredictionHistorySystem.AddPredictionStateReader(Dependency); }
protected override void OnUpdate() { if (!m_GhostCollectionSystem.m_GhostTypeCollection.IsCreated) { return; } var serverTick = m_ClientSimulationSystemGroup.ServerTick; if (m_ClientSimulationSystemGroup.ServerTickFraction < 1) { --serverTick; } if (serverTick != m_GhostPredictionSystemGroup.PredictingTick) { return; } LastBackupTick = serverTick; m_ChildEntityLookup.Clear(); var childCount = m_ChildEntityQuery.CalculateEntityCountWithoutFiltering(); if (childCount > m_ChildEntityLookup.Capacity) { m_ChildEntityLookup.Capacity = childCount; } var buildChildJob = new BuildChildEntityLookupJob { entityType = GetEntityTypeHandle(), childEntityLookup = m_ChildEntityLookup.AsParallelWriter() }; Dependency = buildChildJob.ScheduleParallel(m_ChildEntityQuery, Dependency); var predictionState = PredictionState; var newPredictionState = m_NewPredictionState; var stillUsedPredictionState = m_StillUsedPredictionState; stillUsedPredictionState.Clear(); if (stillUsedPredictionState.Capacity < predictionState.Capacity) { stillUsedPredictionState.Capacity = predictionState.Capacity; } var backupJob = new PredictionBackupJob { predictionState = predictionState, stillUsedPredictionState = stillUsedPredictionState.AsParallelWriter(), newPredictionState = newPredictionState.AsParallelWriter(), ghostType = GetComponentTypeHandle <GhostComponent>(true), entityType = GetEntityTypeHandle(), GhostComponentCollection = m_GhostCollectionSystem.m_GhostComponentCollection, GhostTypeCollection = m_GhostCollectionSystem.m_GhostTypeCollection, GhostComponentIndex = m_GhostCollectionSystem.m_GhostComponentIndex, childEntityLookup = m_ChildEntityLookup, linkedEntityGroupType = GetBufferTypeHandle <LinkedEntityGroup>(), }; Dependency = JobHandle.CombineDependencies(Dependency, m_PredictionStateReadJobHandle); m_PredictionStateReadJobHandle = default; var listLength = m_GhostCollectionSystem.m_GhostComponentCollection.Length; if (listLength <= 32) { var dynamicListJob = new PredictionBackupJob32 { Job = backupJob }; DynamicTypeList.PopulateList(this, m_GhostCollectionSystem.m_GhostComponentCollection, true, ref dynamicListJob.List); Dependency = dynamicListJob.ScheduleParallel(m_PredictionQuery, Dependency); } else if (listLength <= 64) { var dynamicListJob = new PredictionBackupJob64 { Job = backupJob }; DynamicTypeList.PopulateList(this, m_GhostCollectionSystem.m_GhostComponentCollection, true, ref dynamicListJob.List); Dependency = dynamicListJob.ScheduleParallel(m_PredictionQuery, Dependency); } else if (listLength <= 128) { var dynamicListJob = new PredictionBackupJob128 { Job = backupJob }; DynamicTypeList.PopulateList(this, m_GhostCollectionSystem.m_GhostComponentCollection, true, ref dynamicListJob.List); Dependency = dynamicListJob.ScheduleParallel(m_PredictionQuery, Dependency); } else { throw new System.InvalidOperationException( $"Too many ghost component types present in project, limit is {DynamicTypeList.MaxCapacity} types. This is any struct which has a field marked with GhostField attribute."); } Job.WithCode(() => { var keys = predictionState.GetKeyArray(Allocator.Temp); for (int i = 0; i < keys.Length; ++i) { if (!stillUsedPredictionState.TryGetValue(keys[i], out var temp)) { // Free the memory and remove the chunk from the lookup predictionState.TryGetValue(keys[i], out var alloc); UnsafeUtility.Free((void *)alloc, Allocator.Persistent); predictionState.Remove(keys[i]); } } while (newPredictionState.TryDequeue(out var newState)) { if (!predictionState.TryAdd(newState.chunk, newState.data)) { // Remove the old value, free it and add the new one - this happens when a chunk is reused too quickly predictionState.TryGetValue(newState.chunk, out var alloc); UnsafeUtility.Free((void *)alloc, Allocator.Persistent); predictionState.Remove(newState.chunk); // And add it again predictionState.TryAdd(newState.chunk, newState.data); } } }).Schedule(); PredictionStateWriteJobHandle = Dependency; }
protected override void OnUpdate() { if (!m_GhostCollectionSystem.m_GhostTypeCollection.IsCreated) { return; } if (m_GhostPredictionSystemGroup.PredictingTick != m_GhostPredictionHistorySystem.LastBackupTick) { return; } if (m_PredictionErrors.Length != m_GhostCollectionSystem.PredictionErrorCount * JobsUtility.MaxJobThreadCount) { m_PredictionErrors.Dispose(); m_PredictionErrors = new NativeArray <float>(m_GhostCollectionSystem.PredictionErrorCount * JobsUtility.MaxJobThreadCount, Allocator.Persistent); } for (int job = 1; job < JobsUtility.MaxJobThreadCount; ++job) { for (int i = 0; i < m_GhostCollectionSystem.PredictionErrorCount; ++i) { m_PredictionErrors[i] = math.max(m_PredictionErrors[i], m_PredictionErrors[m_GhostCollectionSystem.PredictionErrorCount * job + i]); } } World.GetExistingSystem <GhostStatsCollectionSystem>().AddPredictionErrorStats(m_PredictionErrors.GetSubArray(0, m_GhostCollectionSystem.PredictionErrorCount)); // Clear UnsafeUtility.MemClear(m_PredictionErrors.GetUnsafePtr(), 4 * m_GhostCollectionSystem.PredictionErrorCount * JobsUtility.MaxJobThreadCount); m_ChildEntityLookup.Clear(); var childCount = m_ChildEntityQuery.CalculateEntityCountWithoutFiltering(); if (childCount > m_ChildEntityLookup.Capacity) { m_ChildEntityLookup.Capacity = childCount; } var buildChildJob = new BuildChildEntityLookupJob { entityType = GetEntityTypeHandle(), childEntityLookup = m_ChildEntityLookup.AsParallelWriter() }; Dependency = buildChildJob.ScheduleParallel(m_ChildEntityQuery, Dependency); var debugJob = new PredictionDebugJob { predictionState = m_GhostPredictionHistorySystem.PredictionState, ghostType = GetComponentTypeHandle <GhostComponent>(true), predictedGhostType = GetComponentTypeHandle <PredictedGhostComponent>(true), entityType = GetEntityTypeHandle(), GhostComponentCollection = m_GhostCollectionSystem.m_GhostComponentCollection, GhostTypeCollection = m_GhostCollectionSystem.m_GhostTypeCollection, GhostComponentIndex = m_GhostCollectionSystem.m_GhostComponentIndex, childEntityLookup = m_ChildEntityLookup, linkedEntityGroupType = GetBufferTypeHandle <LinkedEntityGroup>(), tick = m_GhostPredictionSystemGroup.PredictingTick, translationType = ComponentType.ReadWrite <Translation>(), predictionErrors = m_PredictionErrors, numPredictionErrors = m_GhostCollectionSystem.PredictionErrorCount }; Dependency = JobHandle.CombineDependencies(Dependency, m_GhostPredictionHistorySystem.PredictionStateWriteJobHandle); var listLength = m_GhostCollectionSystem.m_GhostComponentCollection.Length; if (listLength <= 32) { var dynamicListJob = new PredictionDebugJob32 { Job = debugJob }; DynamicTypeList.PopulateList(this, m_GhostCollectionSystem.m_GhostComponentCollection, true, ref dynamicListJob.List); Dependency = dynamicListJob.ScheduleParallel(m_PredictionQuery, Dependency); } else if (listLength <= 64) { var dynamicListJob = new PredictionDebugJob64 { Job = debugJob }; DynamicTypeList.PopulateList(this, m_GhostCollectionSystem.m_GhostComponentCollection, true, ref dynamicListJob.List); Dependency = dynamicListJob.ScheduleParallel(m_PredictionQuery, Dependency); } else if (listLength <= 128) { var dynamicListJob = new PredictionDebugJob128 { Job = debugJob }; DynamicTypeList.PopulateList(this, m_GhostCollectionSystem.m_GhostComponentCollection, true, ref dynamicListJob.List); Dependency = dynamicListJob.ScheduleParallel(m_PredictionQuery, Dependency); } else { throw new System.InvalidOperationException( $"Too many ghost component types present in project, limit is {DynamicTypeList.MaxCapacity} types. This is any struct which has a field marked with GhostField attribute."); } m_GhostPredictionHistorySystem.AddPredictionStateReader(Dependency); }