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);
                }
            }
        }
Exemple #3
0
        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();
            }
        }
Exemple #5
0
 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++);
 }
Exemple #6
0
            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);
                }
            }
Exemple #7
0
        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();
            }
        }
Exemple #8
0
        /// <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();
        }
Exemple #9
0
    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();
    }
Exemple #10
0
        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);
            }
        }
Exemple #11
0
    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));
    }
Exemple #13
0
        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));
        }
Exemple #14
0
        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);
        }
Exemple #15
0
    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));
    }
Exemple #16
0
            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;
                }
            }
Exemple #17
0
    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);
    }