protected override void OnUpdate() { Entities.WithNone <SendRpcCommandRequestComponent>().ForEach((Entity reqEnt, ref FireRpc req, ref ReceiveRpcCommandRequestComponent reqSrc) => { PostUpdateCommands.DestroyEntity(reqEnt); m_Queue.Enqueue(req); }); uint renderTick = m_NetworkTime.interpolateTargetTick; while (m_Queue.Count > 0) { var msg = m_Queue.Peek(); if (msg.Tick > renderTick) { break; } m_Queue.Dequeue(); if (!m_GhostUpdateSystemGroup.GhostMap.TryGetValue(msg.OwnerGId, out GhostEntity item)) { return; } int localGhostId = EntityManager .GetComponentData <GhostComponent>(GetSingleton <CommandTargetComponent>().Target).Id; // 开枪人收到确认消息 if (localGhostId == msg.OwnerGId) { return; } Transform mcc = EntityManager.GetComponentObject <Transform>(item.Entity); LinkedPlayerView linkedView = mcc.GetComponent <GameObjectLinked>().Target .GetComponent <LinkedPlayerView>(); linkedView.GenProjectile(World, msg.Pos, msg.Dir, false); Debug.Log($"收到开枪."); } NetDebug.Set($"开枪消息队列", m_Queue.Count); // 处理命中消息 Entities.WithNone <SendRpcCommandRequestComponent>().ForEach((Entity reqEnt, ref ProjectileHit hit, ref ReceiveRpcCommandRequestComponent reqSrc) => { PostUpdateCommands.DestroyEntity(reqEnt); if (!m_GhostUpdateSystemGroup.GhostMap.TryGetValue(hit.GId, out GhostEntity item)) { return; } var gcv = EntityManager.GetComponentObject <GameObjectLinked>(item.Entity).Target; gcv.GetComponent <PlayerHUD>()?.SetValue(hit.Hp / 100f); NetDebug.Set($"命中GhostId", $"Id={hit.GId} Hp={hit.Hp}"); }); }
protected override void OnUpdate() { uint interpolatedTick = _networkTimeSystem.interpolateTargetTick; uint predictedTick = _networkTimeSystem.predictTargetTick; var commandBuffer = _barrier.CreateCommandBuffer(); // 插值类型的Ghost销毁 while (_interpolatedDespawnQueue.Count > 0 && !SequenceHelpers.IsNewer(_interpolatedDespawnQueue.Peek().Tick, interpolatedTick)) { var desspawnGhost = _interpolatedDespawnQueue.Dequeue(); if (_ghostReceiveSystem.SpawnedGhostEntityMap.TryGetValue(desspawnGhost.Ghost, out Entity ent)) { commandBuffer.DestroyEntity(ent); _ghostReceiveSystem.SpawnedGhostEntityMap.Remove(desspawnGhost.Ghost); } } // 预测类型的Ghost销毁 while (_predictedDespawnQueue.Count > 0 && !SequenceHelpers.IsNewer(_predictedDespawnQueue.Peek().Tick, predictedTick)) { var desspawnGhost = _predictedDespawnQueue.Dequeue(); if (_ghostReceiveSystem.SpawnedGhostEntityMap.TryGetValue(desspawnGhost.Ghost, out Entity ent)) { commandBuffer.DestroyEntity(ent); _ghostReceiveSystem.SpawnedGhostEntityMap.Remove(desspawnGhost.Ghost); } } }
public unsafe void Test() { const int cnt = 1000; using var queue = new NativeQueue <int>(0); var managed = new Queue <int>(cnt); var arr = new int[cnt]; var rand = new Random(); for (int i = 0; i < cnt; i++) { arr[i] = rand.Next(cnt); } for (int i = 0; i < cnt; i++) { managed.Enqueue(arr[i]); queue.Enqueue(arr[i]); } var se = queue.GetEnumerator(); var me = managed.GetEnumerator(); var toArr = queue.ToArray(); for (var i = 0; i < cnt; i++) { se.MoveNext(); me.MoveNext(); Assert.True(se.Current == me.Current); Assert.True(toArr[i] == se.Current); } se.Dispose(); me.Dispose(); for (int i = 0; i < cnt; i++) { Assert.True(managed.Count == queue.Count); var l = managed.Dequeue(); var r = queue.Peek(); Assert.True(l == r); queue.Dequeue(); } queue.Clear(); queue.TrimExcess(); Assert.True(!queue.IsDisposed); queue.Dispose(); Assert.True(queue.Ptr == null); Assert.True(queue.IsDisposed); }
/// <summary> /// Checks if chunk building jobs are ready /// </summary> private IEnumerator ChunkLoading() { var wait = new WaitForSecondsRealtime(1f / buildChecksPerSecond); while (true) { yield return(wait); if (chunkBuildingJobs.Count > 0) { for (int i = 0; i < maxChunksToBuildAtOnce; i++) { if (chunkBuildingJobs.Peek().IsCompleted) { chunkBuildingJobs.Dequeue().Complete(); Chunk tc = terrainChunks.Dequeue(); tc.gameObject.SetActive(true); tc.CreateBiomeTexture(); tc.Animation(); tc.ApplyMesh(); LoadedChunks++; yield return(null); if (chunkBuildingJobs.Count == 0) { break; } // TODO: check if player is close // ChunkLoading(); } else { break; } } } while (meshBakingJobs.Count > 0) { if (meshBakingJobs.Peek().IsCompleted) { meshBakingJobs.Dequeue().Complete(); Chunk chunk = terrainCollisionMeshes.Dequeue(); chunk.BlockMeshCollider.sharedMesh = chunk.BlockMeshFilter.mesh; } } TimeToBuild?.Invoke(); } }
private uint FindGhostId(NativeList <uint> blockedId) { if (m_GhostIdQueue.Count == 0) { return(m_GhostId++); } if (!blockedId.Contains(m_GhostIdQueue.Peek())) { return(m_GhostIdQueue.Dequeue()); } return(m_GhostId++); }
public void Execute() { while (interpolatedDespawnQueue.Count > 0 && !SequenceHelpers.IsNewer(interpolatedDespawnQueue.Peek().tick, interpolatedTick)) { commandBuffer.RemoveComponent(interpolatedDespawnQueue.Dequeue().ghost, ghostType); } while (predictedDespawnQueue.Count > 0 && !SequenceHelpers.IsNewer(predictedDespawnQueue.Peek().tick, predictedTick)) { commandBuffer.RemoveComponent(predictedDespawnQueue.Dequeue().ghost, ghostType); } }
public void NativeQueueAddPeekRemove() { for (int i = 0; i < COUNT; i++) { nq.Enqueue(i); } var peek = nq.Peek(); for (int i = 0; i < COUNT; i++) { var res = nq.Dequeue(); } }
/// <summary> /// Checks if chunk building jobs are ready /// </summary> private void ChunkLoading() { if (pendingJobs.Count > 0) { for (int i = 0; i < maxChunksToBuildAtOnce; i++) { if (pendingJobs.Peek().IsCompleted) { pendingJobs.Dequeue().Complete(); Chunk tc = terrainChunks.Dequeue(); tc.gameObject.SetActive(true); tc.CreateBiomeTexture(); tc.Animation(); tc.ApplyMesh(); LoadedChunks++; if (pendingJobs.Count == 0) { break; } // TODO: check if player is close // ChunkLoading(); } else { break; } } } while (meshBakingJobs.Count > 0) { if (meshBakingJobs.Peek().IsCompleted) { meshBakingJobs.Dequeue().Complete(); Chunk chunk = terrainCollisionMeshes.Dequeue(); chunk.BlockMeshCollider.sharedMesh = chunk.BlockMeshFilter.mesh; } } TimeToBuild.Invoke(); }
public void Enqueue_Dequeue_Peek() { var queue = new NativeQueue <int> (Allocator.Temp); Assert.AreEqual(0, queue.Count); Assert.Throws <System.InvalidOperationException> (() => { queue.Dequeue(); }); for (int i = 0; i < 16; ++i) { queue.Enqueue(i); } Assert.AreEqual(16, queue.Count); for (int i = 0; i < 16; ++i) { Assert.AreEqual(i, queue.Peek(), "Got the wrong value from the queue"); queue.Dequeue(); } Assert.AreEqual(0, queue.Count); Assert.Throws <System.InvalidOperationException> (() => { queue.Dequeue(); }); queue.Dispose(); }
protected override void OnUpdate() { Entities.WithNone <SendRpcCommandRequestComponent>().ForEach((Entity reqEnt, ref GrenadeRpc msg, ref ReceiveRpcCommandRequestComponent reqSrc) => { PostUpdateCommands.DestroyEntity(reqEnt); m_Queue.Enqueue(msg); }); uint renderTick = m_NetworkTime.interpolateTargetTick; while (m_Queue.Count > 0) { var msg = m_Queue.Peek(); if (msg.Tick > renderTick) { break; } m_Queue.Dequeue(); if (!m_GhostUpdateSystemGroup.GhostMap.TryGetValue(msg.OwnerGId, out GhostEntity item)) { return; } int localGhostId = EntityManager .GetComponentData <GhostComponent>(GetSingleton <CommandTargetComponent>().Target).Id; // 开枪人收到确认消息 if (localGhostId == msg.OwnerGId) { return; } Transform mcc = EntityManager.GetComponentObject <Transform>(item.Entity); LinkedPlayerView linkedView = mcc.GetComponent <GameObjectLinked>().Target .GetComponent <LinkedPlayerView>(); linkedView.GenGrenade(World, msg.Pos, msg.Dir, false); } }
void Update() { if (_quadTree.IsCreated == false) { return; } NodeCount = _quadTree.Length; if (_startPos != null && _lastStartPos != _startPos.gameObject.transform.position) { _lastStartPos = _startPos.gameObject.transform.position; _player.transform.position = _lastStartPos; var date = DateTime.UtcNow; path = NativeQuadTreePathFinding.RunAStar(_quadTree, new float2(_lastStartPos.x, _lastStartPos.z), new float2(_lastEndPos.x, _lastEndPos.z), Allocator.Persistent); UnityEngine.Debug.Log((DateTime.UtcNow - date).TotalSeconds); } if (_endPos != null && _lastEndPos != _endPos.gameObject.transform.position) { _lastEndPos = _endPos.gameObject.transform.position; _player.transform.position = _lastStartPos; path = NativeQuadTreePathFinding.RunAStar(_quadTree, new float2(_lastStartPos.x, _lastStartPos.z), new float2(_lastEndPos.x, _lastEndPos.z), Allocator.Persistent); } if (path.IsCreated && path.Count > 0) { var pos = path.Peek(); var v = new float2(pos.x - _player.transform.position.x, pos.y - _player.transform.position.z); if (math.lengthsq(v) < 0.5f) { path.Dequeue(); } else { v = math.normalizesafe(v); _player.transform.position = new Vector3(_player.transform.position.x + v.x * 0.5f, 0, _player.transform.position.z + v.y * 0.5f); } } }
protected override JobHandle OnUpdate(JobHandle inputDeps) { EntityManager.DestroyEntity(m_DestroyGroup); EntityManager.DestroyEntity(m_InvalidGhosts); m_InvalidGhosts.Clear(); var targetTick = NetworkTimeSystem.interpolateTargetTick; m_CurrentDelayedSpawnList.Clear(); while (m_DelayedSpawnQueue.Count > 0 && !SequenceHelpers.IsNewer(m_DelayedSpawnQueue.Peek().spawnTick, targetTick)) { var ghost = m_DelayedSpawnQueue.Dequeue(); GhostEntity gent; if (m_GhostMap.TryGetValue(ghost.ghostId, out gent)) { m_CurrentDelayedSpawnList.Add(ghost); m_InvalidGhosts.Add(gent.entity); } } m_CurrentPredictedSpawnList.Clear(); while (m_PredictedSpawnQueue.Count > 0) { var ghost = m_PredictedSpawnQueue.Dequeue(); GhostEntity gent; if (m_GhostMap.TryGetValue(ghost.ghostId, out gent)) { m_CurrentPredictedSpawnList.Add(ghost); m_InvalidGhosts.Add(gent.entity); } } var delayedEntities = default(NativeArray <Entity>); delayedEntities = new NativeArray <Entity>(m_CurrentDelayedSpawnList.Length, Allocator.TempJob); if (m_CurrentDelayedSpawnList.Length > 0) { EntityManager.CreateEntity(m_Archetype, delayedEntities); } var predictedEntities = default(NativeArray <Entity>); predictedEntities = new NativeArray <Entity>(m_CurrentPredictedSpawnList.Length, Allocator.TempJob); if (m_CurrentPredictedSpawnList.Length > 0) { EntityManager.CreateEntity(m_PredictedArchetype, predictedEntities); } var predictSpawnRequests = m_SpawnRequestGroup.ToEntityArray(Allocator.TempJob); var predictSpawnEntities = new NativeArray <Entity>(predictSpawnRequests.Length, Allocator.TempJob); if (predictSpawnEntities.Length > 0) { EntityManager.CreateEntity(m_PredictedArchetype, predictSpawnEntities); } var newEntities = default(NativeArray <Entity>); newEntities = new NativeArray <Entity>(m_NewGhosts.Length, Allocator.TempJob); if (m_NewGhosts.Length > 0) { EntityManager.CreateEntity(m_InitialArchetype, newEntities); } if (m_CurrentDelayedSpawnList.Length > 0) { var delayedjob = new DelayedSpawnJob { entities = delayedEntities, delayedGhost = m_CurrentDelayedSpawnList, snapshotFromEntity = GetBufferFromEntity <T>(), ghostMap = m_GhostMap, ghostType = GhostType }; inputDeps = delayedjob.Schedule(inputDeps); inputDeps = UpdateNewInterpolatedEntities(delayedEntities, inputDeps); } // FIXME: current and predicted can run in parallel I think if (m_CurrentPredictedSpawnList.Length > 0) { var delayedjob = new DelayedSpawnJob { entities = predictedEntities, delayedGhost = m_CurrentPredictedSpawnList, snapshotFromEntity = GetBufferFromEntity <T>(), ghostMap = m_GhostMap, ghostType = GhostType }; inputDeps = delayedjob.Schedule(inputDeps); inputDeps = UpdateNewPredictedEntities(predictedEntities, inputDeps); } if (predictSpawnRequests.Length > 0) { var spawnJob = new PredictSpawnJob { requests = predictSpawnRequests, entities = predictSpawnEntities, snapshotFromEntity = GetBufferFromEntity <T>(), commandBuffer = m_Barrier.CreateCommandBuffer(), predictSpawnGhosts = m_PredictSpawnGhosts }; inputDeps = spawnJob.Schedule(inputDeps); inputDeps = UpdateNewPredictedEntities(predictSpawnEntities, inputDeps); } m_PredictionSpawnCleanupMap.Clear(); if (m_NewGhosts.Length > 0) { if (m_PredictionSpawnCleanupMap.Capacity < m_NewGhosts.Length) { m_PredictionSpawnCleanupMap.Capacity = m_NewGhosts.Length; } var predictionMask = new NativeArray <int>(m_NewGhosts.Length, Allocator.TempJob); inputDeps = MarkPredictedGhosts(m_NewGhosts, predictionMask, m_PredictSpawnGhosts, inputDeps); var job = new CopyInitialStateJob { entities = newEntities, newGhosts = m_NewGhosts, newGhostIds = m_NewGhostIds, snapshotFromEntity = GetBufferFromEntity <T>(), ghostMap = m_ConcurrentGhostMap, ghostType = GhostType, pendingSpawnQueue = m_ConcurrentDelayedSpawnQueue, predictedSpawnQueue = m_ConcurrentPredictedSpawnQueue, predictionMask = predictionMask, predictionSpawnGhosts = m_PredictSpawnGhosts, predictionSpawnCleanupMap = m_PredictionSpawnCleanupMap.ToConcurrent(), commandBuffer = m_Barrier.CreateCommandBuffer().ToConcurrent() }; inputDeps = job.Schedule(newEntities.Length, 8, inputDeps); } var spawnClearJob = new PredictSpawnCleanupJob { predictionSpawnCleanupMap = m_PredictionSpawnCleanupMap, predictionSpawnGhosts = m_PredictSpawnGhosts, interpolationTarget = targetTick, commandBuffer = m_Barrier.CreateCommandBuffer(), replicatedEntityComponentType = ComponentType.ReadWrite <ReplicatedEntityComponent>() }; inputDeps = spawnClearJob.Schedule(inputDeps); m_Barrier.AddJobHandleForProducer(inputDeps); var clearJob = new ClearNewJob { entities = newEntities, visibleEntities = delayedEntities, visiblePredictedEntities = predictedEntities, newGhosts = m_NewGhosts, newGhostIds = m_NewGhostIds, predictSpawnEntities = predictSpawnEntities, predictSpawnRequests = predictSpawnRequests }; return(clearJob.Schedule(inputDeps)); }
protected override JobHandle OnUpdate(JobHandle inputDeps) { bool didCompleteAll = false; // Entities can contain LinkedEntityGroup, so query based destruction will not always work if (!m_DestroyGroup.IsEmptyIgnoreFilter) { var destroyGroupEntities = m_DestroyGroup.ToEntityArray(Allocator.TempJob); EntityManager.DestroyEntity(destroyGroupEntities); destroyGroupEntities.Dispose(); didCompleteAll = true; } if (m_InvalidGhosts.Length > 0) { EntityManager.DestroyEntity(m_InvalidGhosts); m_InvalidGhosts.Clear(); didCompleteAll = true; } if (m_NewGhosts.Length == 0 && m_DelayedSpawnQueue.Count == 0 && m_PredictedSpawnQueue.Count == 0 && m_SpawnRequestGroup.IsEmptyIgnoreFilter) { return(inputDeps); } if (m_interpolatedPrefab == Entity.Null) { var prefabs = GetSingleton <GhostPrefabCollectionComponent>(); var interpolatedPrefabs = EntityManager.GetBuffer <GhostPrefabBuffer>(prefabs.clientInterpolatedPrefabs); var predictedPrefabs = EntityManager.GetBuffer <GhostPrefabBuffer>(prefabs.clientPredictedPrefabs); for (int i = 0; i < interpolatedPrefabs.Length; ++i) { if (EntityManager.HasComponent <T>(interpolatedPrefabs[i].Value)) { m_interpolatedPrefab = interpolatedPrefabs[i].Value; break; } } for (int i = 0; i < predictedPrefabs.Length; ++i) { if (EntityManager.HasComponent <T>(predictedPrefabs[i].Value)) { m_predictedPrefab = predictedPrefabs[i].Value; break; } } if (m_interpolatedPrefab == Entity.Null || m_predictedPrefab == Entity.Null) { throw new InvalidOperationException(String.Format( "Could not find interpolated/predicted prefabs for {0}, make sure the GhostPrefabCollectionComponent singleton is correct", typeof(T))); } } var interpolationTargetTick = m_ClientSimulationSystemGroup.InterpolationTick; var predictionTargetTick = m_ClientSimulationSystemGroup.ServerTick; m_CurrentDelayedSpawnList.Clear(); while (m_DelayedSpawnQueue.Count > 0 && !SequenceHelpers.IsNewer(m_DelayedSpawnQueue.Peek().spawnTick, interpolationTargetTick)) { if (!didCompleteAll) { // This will trigger a structural change anyway, so just complete here EntityManager.CompleteAllJobs(); didCompleteAll = true; } var ghost = m_DelayedSpawnQueue.Dequeue(); GhostEntity gent; if (m_GhostMap.TryGetValue(ghost.ghostId, out gent) && gent.entity == ghost.oldEntity) { m_CurrentDelayedSpawnList.Add(ghost); m_InvalidGhosts.Add(gent.entity); } } m_CurrentPredictedSpawnList.Clear(); while (m_PredictedSpawnQueue.Count > 0 && !SequenceHelpers.IsNewer(m_PredictedSpawnQueue.Peek().spawnTick, predictionTargetTick)) { if (!didCompleteAll) { // This will trigger a structural change anyway, so just complete here EntityManager.CompleteAllJobs(); didCompleteAll = true; } var ghost = m_PredictedSpawnQueue.Dequeue(); GhostEntity gent; if (m_GhostMap.TryGetValue(ghost.ghostId, out gent) && gent.entity == ghost.oldEntity) { m_CurrentPredictedSpawnList.Add(ghost); m_InvalidGhosts.Add(gent.entity); } } var delayedEntities = default(NativeArray <Entity>); delayedEntities = new NativeArray <Entity>(m_CurrentDelayedSpawnList.Length, Allocator.TempJob); if (m_CurrentDelayedSpawnList.Length > 0) { EntityManager.Instantiate(m_interpolatedPrefab, delayedEntities); } var predictedEntities = default(NativeArray <Entity>); predictedEntities = new NativeArray <Entity>(m_CurrentPredictedSpawnList.Length, Allocator.TempJob); if (m_CurrentPredictedSpawnList.Length > 0) { EntityManager.Instantiate(m_predictedPrefab, predictedEntities); } var predictSpawnRequests = m_SpawnRequestGroup.ToEntityArray(Allocator.TempJob); var predictSpawnEntities = new NativeArray <Entity>(predictSpawnRequests.Length, Allocator.TempJob); if (predictSpawnEntities.Length > 0) { EntityManager.Instantiate(m_predictedPrefab, predictSpawnEntities); } var newEntities = default(NativeArray <Entity>); newEntities = new NativeArray <Entity>(m_NewGhosts.Length, Allocator.TempJob); if (m_NewGhosts.Length > 0) { EntityManager.CreateEntity(m_InitialArchetype, newEntities); } if (m_CurrentDelayedSpawnList.Length > 0) { var delayedjob = new DelayedSpawnJob { entities = delayedEntities, delayedGhost = m_CurrentDelayedSpawnList, snapshotFromEntity = GetBufferFromEntity <T>(), ghostFromEntity = GetComponentDataFromEntity <GhostComponent>(), ghostMap = m_GhostMap, ghostType = GhostType }; inputDeps = delayedjob.Schedule(inputDeps); m_GhostUpdateSystemGroup.LastGhostMapWriter = inputDeps; inputDeps = UpdateNewInterpolatedEntities(delayedEntities, inputDeps); } // FIXME: current and predicted can run in parallel I think if (m_CurrentPredictedSpawnList.Length > 0) { var delayedjob = new DelayedSpawnJob { entities = predictedEntities, delayedGhost = m_CurrentPredictedSpawnList, snapshotFromEntity = GetBufferFromEntity <T>(), ghostFromEntity = GetComponentDataFromEntity <GhostComponent>(), ghostMap = m_GhostMap, ghostType = GhostType }; inputDeps = delayedjob.Schedule(inputDeps); m_GhostUpdateSystemGroup.LastGhostMapWriter = inputDeps; inputDeps = UpdateNewPredictedEntities(predictedEntities, inputDeps); } if (predictSpawnRequests.Length > 0) { var spawnJob = new PredictSpawnJob { requests = predictSpawnRequests, entities = predictSpawnEntities, snapshotFromEntity = GetBufferFromEntity <T>(), commandBuffer = m_Barrier.CreateCommandBuffer(), predictSpawnGhosts = m_PredictSpawnGhosts }; inputDeps = spawnJob.Schedule(inputDeps); inputDeps = UpdateNewPredictedEntities(predictSpawnEntities, inputDeps); } m_PredictionSpawnCleanupMap.Clear(); if (m_NewGhosts.Length > 0) { if (m_PredictionSpawnCleanupMap.Capacity < m_NewGhosts.Length) { m_PredictionSpawnCleanupMap.Capacity = m_NewGhosts.Length; } NativeArray <int> predictionMask = new NativeArray <int>(m_NewGhosts.Length, Allocator.TempJob); inputDeps = SetPredictedGhostDefaults(m_NewGhosts, predictionMask, inputDeps); inputDeps = MarkPredictedGhosts(m_NewGhosts, predictionMask, m_PredictSpawnGhosts, inputDeps); var job = new CopyInitialStateJob { entities = newEntities, newGhosts = m_NewGhosts, newGhostIds = m_NewGhostIds, snapshotFromEntity = GetBufferFromEntity <T>(), ghostMap = m_ConcurrentGhostMap, ghostType = GhostType, pendingSpawnQueue = m_ConcurrentDelayedSpawnQueue, predictedSpawnQueue = m_ConcurrentPredictedSpawnQueue, predictionMask = predictionMask, predictionSpawnGhosts = m_PredictSpawnGhosts, predictionSpawnCleanupMap = m_PredictionSpawnCleanupMap.AsParallelWriter(), commandBuffer = m_Barrier.CreateCommandBuffer().ToConcurrent() }; inputDeps = job.Schedule(newEntities.Length, 8, inputDeps); m_GhostUpdateSystemGroup.LastGhostMapWriter = inputDeps; } var spawnClearJob = new PredictSpawnCleanupJob { predictionSpawnCleanupMap = m_PredictionSpawnCleanupMap, predictionSpawnGhosts = m_PredictSpawnGhosts, interpolationTarget = interpolationTargetTick, commandBuffer = m_Barrier.CreateCommandBuffer(), ghostComponentType = ComponentType.ReadWrite <GhostComponent>() }; inputDeps = spawnClearJob.Schedule(inputDeps); m_Barrier.AddJobHandleForProducer(inputDeps); var clearJob = new ClearNewJob { entities = newEntities, visibleEntities = delayedEntities, visiblePredictedEntities = predictedEntities, newGhosts = m_NewGhosts, newGhostIds = m_NewGhostIds, predictSpawnEntities = predictSpawnEntities, predictSpawnRequests = predictSpawnRequests }; return(clearJob.Schedule(inputDeps)); }
protected override unsafe void OnUpdate() { if (!HasSingleton <GhostPrefabCollectionComponent>() || !HasSingleton <GhostSpawnQueueComponent>()) { return; } var collections = GetSingleton <GhostPrefabCollectionComponent>(); var ghostSpawnEntity = GetSingletonEntity <GhostSpawnQueueComponent>(); var ghostSpawnBufferComponent = EntityManager.GetBuffer <GhostSpawnBuffer>(ghostSpawnEntity); var snapshotDataBufferComponent = EntityManager.GetBuffer <SnapshotDataBuffer>(ghostSpawnEntity); var ghostSpawnBuffer = ghostSpawnBufferComponent.ToNativeArray(Allocator.Temp); var snapshotDataBuffer = snapshotDataBufferComponent.ToNativeArray(Allocator.Temp); ghostSpawnBufferComponent.ResizeUninitialized(0); snapshotDataBufferComponent.ResizeUninitialized(0); var spawnedGhosts = new NativeList <SpawnedGhostMapping>(16, Allocator.Temp); var nonSpawnedGhosts = new NativeList <NonSpawnedGhostMapping>(16, Allocator.Temp); for (int i = 0; i < ghostSpawnBuffer.Length; i++) { var clientPredictionPrefabs = EntityManager.GetBuffer <GhostPrefabBuffer>(collections.ClientPredictedPrefabs); var ghost = ghostSpawnBuffer[i]; Entity entity = Entity.Null; byte * snapshotData = null; // 包含tick var snapshotSize = _ghostCollectionSystem.GhostTypeCollection[ghost.GhostType].SnapshotSize; // Debug.Log($"SpawnGhost:{ghost.GhostId} {ghost.GhostType} {ghost.SpawnType}"); if (ghost.SpawnType == GhostSpawnBuffer.Type.Interpolated) { // 为了可以延迟创建 entity = EntityManager.CreateEntity(ComponentType.ReadOnly <GhostDelaySpawnComponent>()); EntityManager.AddComponentData(entity, new GhostComponent { Id = ghost.GhostId, GhostType = ghost.GhostType, SpawnTick = ghost.ServerSpawnTick }); var newBuffer = EntityManager.AddBuffer <SnapshotDataBuffer>(entity); newBuffer.ResizeUninitialized(snapshotSize * GlobalConstants.SnapshotHistorySize); snapshotData = (byte *)newBuffer.GetUnsafePtr(); EntityManager.AddComponentData(entity, new SnapshotData { SnapshotSize = snapshotSize, LatestIndex = 0 }); _delayedSpawnQueue.Enqueue(new DelayedSpawnGhost { GhostId = ghost.GhostId, GhostType = ghost.GhostType, ClientSpawnTick = ghost.ClientSpawnTick, ServerSpawnTick = ghost.ServerSpawnTick, OldEntity = entity }); nonSpawnedGhosts.Add(new NonSpawnedGhostMapping { GhostId = ghost.GhostId, Entity = entity }); } else if (ghost.SpawnType == GhostSpawnBuffer.Type.Predicted) { entity = ghost.PredictedSpawnEntity != Entity.Null ? ghost.PredictedSpawnEntity : EntityManager.Instantiate(clientPredictionPrefabs[ghost.GhostType].Value); EntityManager.SetComponentData(entity, new GhostComponent { Id = ghost.GhostId, GhostType = ghost.GhostType, SpawnTick = ghost.ServerSpawnTick, }); var newBuffer = EntityManager.GetBuffer <SnapshotDataBuffer>(entity); newBuffer.ResizeUninitialized(snapshotSize * GlobalConstants.SnapshotHistorySize); snapshotData = (byte *)newBuffer.GetUnsafePtr(); EntityManager.SetComponentData(entity, new SnapshotData { SnapshotSize = snapshotSize, LatestIndex = 0 }); spawnedGhosts.Add(new SpawnedGhostMapping { Ghost = new SpawnedGhost { GhostId = ghost.GhostId, SpawnTick = ghost.ServerSpawnTick }, Entity = entity }); } if (entity != Entity.Null) { UnsafeUtility.MemClear(snapshotData, snapshotSize * GlobalConstants.SnapshotHistorySize); UnsafeUtility.MemCpy(snapshotData, (byte *)snapshotDataBuffer.GetUnsafeReadOnlyPtr() + ghost.DataOffset, snapshotSize); } } // 添加到接收系统中 _ghostRecvSystem.AddNonSpawnedGhosts(nonSpawnedGhosts); _ghostRecvSystem.AddSpawnedGhosts(spawnedGhosts); spawnedGhosts.Clear(); while (_delayedSpawnQueue.Count > 0 && SequenceHelpers.IsNewer(_networkTimeSystem.interpolateTargetTick, _delayedSpawnQueue.Peek().ClientSpawnTick)) { var clientInterpolatedPrefabs = EntityManager.GetBuffer <GhostPrefabBuffer>(collections.ClientInterpolatedPrefabs); var ghost = _delayedSpawnQueue.Dequeue(); Entity entity = EntityManager.Instantiate(clientInterpolatedPrefabs[ghost.GhostType].Value); EntityManager.SetComponentData(entity, EntityManager.GetComponentData <SnapshotData>(ghost.OldEntity)); var ghostCompData = EntityManager.GetComponentData <GhostComponent>(ghost.OldEntity); EntityManager.SetComponentData(entity, ghostCompData); var oldBuffer = EntityManager.GetBuffer <SnapshotDataBuffer>(ghost.OldEntity) .ToNativeArray(Allocator.Temp); var newBuffer = EntityManager.GetBuffer <SnapshotDataBuffer>(entity); newBuffer.ResizeUninitialized(oldBuffer.Length); UnsafeUtility.MemCpy(newBuffer.GetUnsafePtr(), oldBuffer.GetUnsafeReadOnlyPtr(), oldBuffer.Length); EntityManager.DestroyEntity(ghost.OldEntity); spawnedGhosts.Add(new SpawnedGhostMapping { Ghost = new SpawnedGhost { GhostId = ghost.GhostId, SpawnTick = ghostCompData.SpawnTick }, Entity = entity, PreviousEntity = ghost.OldEntity }); } _ghostRecvSystem.UpdateSpawnedGhosts(spawnedGhosts); }
protected override JobHandle OnUpdate(JobHandle inputDeps) { EntityManager.DestroyEntity(m_DestroyGroup); EntityManager.DestroyEntity(m_InvalidGhosts); m_InvalidGhosts.Clear(); var targetTick = NetworkTimeSystem.interpolateTargetTick; m_CurrentDelayedSpawnList.Clear(); while (m_DelayedSpawnQueue.Count > 0 && !SequenceHelpers.IsNewer(m_DelayedSpawnQueue.Peek().spawnTick, targetTick)) { var ghost = m_DelayedSpawnQueue.Dequeue(); GhostReceiveSystem.GhostEntity gent; if (m_GhostMap.TryGetValue(ghost.ghostId, out gent)) { m_CurrentDelayedSpawnList.Add(ghost); m_InvalidGhosts.Add(gent.entity); } } var delayedEntities = default(NativeArray <Entity>); delayedEntities = new NativeArray <Entity>(m_CurrentDelayedSpawnList.Length, Allocator.TempJob); if (m_CurrentDelayedSpawnList.Length > 0) { EntityManager.CreateEntity(m_Archetype, delayedEntities); } var entities = default(NativeArray <Entity>); entities = new NativeArray <Entity>(m_NewGhosts.Length, Allocator.TempJob); if (m_NewGhosts.Length > 0) { EntityManager.CreateEntity(m_InitialArchetype, entities); } if (m_CurrentDelayedSpawnList.Length > 0) { var delayedjob = new DelayedSpawnJob { entities = delayedEntities, delayedGhost = m_CurrentDelayedSpawnList, snapshotFromEntity = GetBufferFromEntity <T>(), ghostMap = m_GhostMap, ghostType = GhostType }; inputDeps = delayedjob.Schedule(inputDeps); inputDeps = UpdateNewEntities(delayedEntities, inputDeps); } if (m_NewGhosts.Length > 0) { var job = new CopyInitialStateJob { entities = entities, newGhosts = m_NewGhosts, newGhostIds = m_NewGhostIds, snapshotFromEntity = GetBufferFromEntity <T>(), ghostMap = m_ConcurrentGhostMap, ghostType = GhostType, pendingSpawnQueue = m_ConcurrentDelayedSpawnQueue }; inputDeps = job.Schedule(entities.Length, 8, inputDeps); } var clearJob = new ClearNewJob { entities = entities, visibleEntities = delayedEntities, newGhosts = m_NewGhosts, newGhostIds = m_NewGhostIds, }; return(clearJob.Schedule(inputDeps)); }
public unsafe void Execute() { // FIXME: should handle any number of connections with individual ghost mappings for each #if ENABLE_UNITY_COLLECTIONS_CHECKS if (players.Length > 1) { throw new InvalidOperationException("Ghost receive system only supports a single connection"); } #endif while (delayedDespawnQueue.Count > 0 && !SequenceHelpers.IsNewer(delayedDespawnQueue.Peek().tick, targetTick)) { commandBuffer.RemoveComponent(delayedDespawnQueue.Dequeue().ghost, replicatedEntityType); } var snapshot = snapshotFromEntity[players[0]]; if (snapshot.Length == 0) { return; } var dataStream = DataStreamUnsafeUtility.CreateReaderFromExistingData((byte *)snapshot.GetUnsafePtr(), snapshot.Length); // Read the ghost stream // find entities to spawn or destroy var readCtx = new DataStreamReader.Context(); var serverTick = dataStream.ReadUInt(ref readCtx); var ack = snapshotAckFromEntity[players[0]]; if (ack.LastReceivedSnapshotByLocal != 0 && !SequenceHelpers.IsNewer(serverTick, ack.LastReceivedSnapshotByLocal)) { return; } if (ack.LastReceivedSnapshotByLocal != 0) { ack.ReceivedSnapshotByLocalMask <<= (int)(serverTick - ack.LastReceivedSnapshotByLocal); } ack.ReceivedSnapshotByLocalMask |= 1; ack.LastReceivedSnapshotByLocal = serverTick; snapshotAckFromEntity[players[0]] = ack; uint despawnLen = dataStream.ReadUInt(ref readCtx); uint updateLen = dataStream.ReadUInt(ref readCtx); #if ENABLE_UNITY_COLLECTIONS_CHECKS int startPos = dataStream.GetBitsRead(ref readCtx); #endif for (var i = 0; i < despawnLen; ++i) { int ghostId = (int)dataStream.ReadPackedUInt(ref readCtx, compressionModel); GhostEntity ent; if (!ghostEntityMap.TryGetValue(ghostId, out ent)) { continue; } ghostEntityMap.Remove(ghostId); // if predicted, despawn now, otherwise wait if (predictedFromEntity.Exists(ent.entity)) { commandBuffer.RemoveComponent(ent.entity, replicatedEntityType); } else { delayedDespawnQueue.Enqueue(new DelayedDespawnGhost { ghost = ent.entity, tick = serverTick }); } } #if ENABLE_UNITY_COLLECTIONS_CHECKS netStats[0] = despawnLen; netStats[1] = (uint)(dataStream.GetBitsRead(ref readCtx) - startPos); netStats[2] = 0; for (int i = 0; i < serializers.Length; ++i) { netStats[i * 3 + 3] = 0; netStats[i * 3 + 4] = 0; netStats[i * 3 + 5] = 0; } uint statCount = 0; uint uncompressedCount = 0; #endif uint targetArch = 0; uint targetArchLen = 0; uint baselineTick = 0; uint baselineTick2 = 0; uint baselineTick3 = 0; uint baselineLen = 0; int newGhosts = 0; for (var i = 0; i < updateLen; ++i) { if (targetArchLen == 0) { #if ENABLE_UNITY_COLLECTIONS_CHECKS int curPos = dataStream.GetBitsRead(ref readCtx); if (statCount > 0) { int statType = (int)targetArch; netStats[statType * 3 + 3] = netStats[statType * 3 + 3] + statCount; netStats[statType * 3 + 4] = netStats[statType * 3 + 4] + (uint)(curPos - startPos); netStats[statType * 3 + 5] = netStats[statType * 3 + 5] + uncompressedCount; } startPos = curPos; statCount = 0; uncompressedCount = 0; #endif targetArch = dataStream.ReadPackedUInt(ref readCtx, compressionModel); targetArchLen = dataStream.ReadPackedUInt(ref readCtx, compressionModel); } --targetArchLen; if (baselineLen == 0) { baselineTick = serverTick - dataStream.ReadPackedUInt(ref readCtx, compressionModel); baselineTick2 = serverTick - dataStream.ReadPackedUInt(ref readCtx, compressionModel); baselineTick3 = serverTick - dataStream.ReadPackedUInt(ref readCtx, compressionModel); baselineLen = dataStream.ReadPackedUInt(ref readCtx, compressionModel); } --baselineLen; int ghostId = (int)dataStream.ReadPackedUInt(ref readCtx, compressionModel); GhostEntity gent; if (ghostEntityMap.TryGetValue(ghostId, out gent)) { #if ENABLE_UNITY_COLLECTIONS_CHECKS if (gent.ghostType != targetArch) { throw new InvalidOperationException("Received a ghost with an invalid ghost type"); } //throw new InvalidOperationException("Received a ghost with an invalid ghost type " + targetArch + ", expected " + gent.ghostType); #endif serializers.Deserialize((int)targetArch, gent.entity, serverTick, baselineTick, baselineTick2, baselineTick3, dataStream, ref readCtx, compressionModel); } else { ++newGhosts; serializers.Spawn((int)targetArch, ghostId, serverTick, dataStream, ref readCtx, compressionModel); } #if ENABLE_UNITY_COLLECTIONS_CHECKS ++statCount; if (baselineTick == serverTick) { ++uncompressedCount; } #endif } #if ENABLE_UNITY_COLLECTIONS_CHECKS if (statCount > 0) { int curPos = dataStream.GetBitsRead(ref readCtx); int statType = (int)targetArch; netStats[statType * 3 + 3] = netStats[statType * 3 + 3] + statCount; netStats[statType * 3 + 4] = netStats[statType * 3 + 4] + (uint)(curPos - startPos); netStats[statType * 3 + 5] = netStats[statType * 3 + 5] + uncompressedCount; } #endif while (ghostEntityMap.Capacity < ghostEntityMap.Length + newGhosts) { ghostEntityMap.Capacity += 1024; } }
public void ProcessAnimation(AnimationStream stream) { if (!m_AimDirectionInitialized) { m_CurrentYaw = animState.aimYaw; m_CurrentPitch = animState.aimPitch; m_AimDirectionInitialized = true; } // TODO: (sunek) Get rid of stuttering var t = settings.stiffness * stream.deltaTime; m_CurrentYaw = Mathf.LerpAngle(m_CurrentYaw, animState.aimYaw, t); m_CurrentPitch = Mathf.LerpAngle(m_CurrentPitch, animState.aimPitch, t); var deltaYaw = Mathf.DeltaAngle(animState.aimYaw, m_CurrentYaw); var deltaPitch = Mathf.DeltaAngle(animState.aimPitch, m_CurrentPitch); var deltaRotation = Quaternion.Euler(new Vector3(-deltaPitch, deltaYaw, 0)); var angle = Quaternion.Angle(Quaternion.identity, deltaRotation); if (angle > settings.maxAngle) { t = settings.maxAngle / angle; m_CurrentYaw = Mathf.LerpAngle(animState.aimYaw, m_CurrentYaw, t); m_CurrentPitch = Mathf.LerpAngle(animState.aimPitch, m_CurrentPitch, t); deltaYaw = Mathf.DeltaAngle(animState.aimYaw, m_CurrentYaw); deltaPitch = Mathf.DeltaAngle(animState.aimPitch, m_CurrentPitch); deltaRotation = Quaternion.Euler(new Vector3(-deltaPitch, deltaYaw, 0)); } if (m_DragHistory.Count <= settings.rollDelay) { m_DragHistory.Enqueue(deltaRotation); } var drag = Quaternion.SlerpUnclamped(Quaternion.identity, deltaRotation, settings.dragWeight); var roll = m_DragHistory.Count < settings.rollDelay + 1 ? m_DragHistory.Peek() : m_DragHistory.Dequeue(); roll = Quaternion.SlerpUnclamped(Quaternion.identity, new Quaternion(0f, roll.y, 0f, roll.w), settings.rollWeight); var handPosition = m_Effectorhandle.GetPosition(stream); var handRotation = m_Effectorhandle.GetRotation(stream); var weaponPivotPosition = m_WeaponPivot.GetPosition(stream); var weaponPivotRotation = m_WeaponPivot.GetRotation(stream); var dragPivot = weaponPivotRotation * settings.dragPivot; var rollPivot = weaponPivotRotation * settings.rollPivot; var dragPivotDelta = handPosition - (weaponPivotPosition + dragPivot); var rollPivotDelta = handPosition - (weaponPivotPosition + rollPivot); var handOffset = drag * dragPivotDelta; handOffset = handOffset - dragPivotDelta; var rollOffset = roll * rollPivotDelta; rollOffset = rollOffset - rollPivotDelta; handPosition = handPosition + handOffset + rollOffset; handRotation = drag * handRotation * roll; m_WeaponHandResult.SetPosition(stream, handPosition); m_WeaponHandResult.SetRotation(stream, handRotation); }