Beispiel #1
0
        protected override JobHandle OnUpdate(JobHandle inputDeps)
        {
            m_SerialSpawnChunks.Clear();
            // Make sure the list of connections and connection state is up to date
            var connections = connectionGroup.ToEntityArray(Allocator.TempJob);
            var existing    = new NativeHashMap <Entity, int>(connections.Length, Allocator.Temp);

            for (int i = 0; i < connections.Length; ++i)
            {
                existing.TryAdd(connections[i], 1);
                int stateIndex;
                if (!m_ConnectionStateLookup.TryGetValue(connections[i], out stateIndex))
                {
                    m_ConnectionStates.Add(new ConnectionStateData
                    {
                        Entity             = connections[i],
                        SerializationState = new NativeHashMap <ArchetypeChunk, SerializationState>(1024, Allocator.Persistent)
                    });
                    m_ConnectionStateLookup.TryAdd(connections[i], m_ConnectionStates.Count - 1);
                }
            }

            connections.Dispose();

            for (int i = 0; i < m_ConnectionStates.Count; ++i)
            {
                int val;
                if (!existing.TryGetValue(m_ConnectionStates[i].Entity, out val))
                {
                    m_ConnectionStateLookup.Remove(m_ConnectionStates[i].Entity);
                    m_ConnectionStates[i].Dispose();
                    if (i != m_ConnectionStates.Count - 1)
                    {
                        m_ConnectionStates[i] = m_ConnectionStates[m_ConnectionStates.Count - 1];
                        m_ConnectionStateLookup.Remove(m_ConnectionStates[i].Entity);
                        m_ConnectionStateLookup.TryAdd(m_ConnectionStates[i].Entity, i);
                    }

                    m_ConnectionStates.RemoveAt(m_ConnectionStates.Count - 1);
                }
            }

            // Find the latest tick which has been acknowledged by all clients and cleanup all ghosts destroyed ebfore that
            uint currentTick = m_ServerSimulation.ServerTick;

            var ackedByAll = new NativeArray <uint>(1, Allocator.TempJob);

            ackedByAll[0] = currentTick;
            var findAckJob = new FindAckedByAllJob
            {
                tick = ackedByAll
            };

            inputDeps = findAckJob.ScheduleSingle(this, inputDeps);

            EntityCommandBuffer commandBuffer = m_Barrier.CreateCommandBuffer();
            var ghostCleanupJob = new CleanupGhostJob
            {
                currentTick    = currentTick,
                tick           = ackedByAll,
                commandBuffer  = commandBuffer.ToConcurrent(),
                freeGhostIds   = m_FreeGhostIds.AsParallelWriter(),
                ghostStateType = ComponentType.ReadWrite <GhostSystemStateComponent>()
            };

            inputDeps = ghostCleanupJob.Schedule(this, inputDeps);


            var entityType           = GetArchetypeChunkEntityType();
            var ghostSystemStateType = GetArchetypeChunkComponentType <GhostSystemStateComponent>();

            serializers.BeginSerialize(this);

            // Extract all newly spawned ghosts and set their ghost ids
            JobHandle spawnChunkHandle;
            var       spawnChunks = ghostSpawnGroup.CreateArchetypeChunkArray(Allocator.TempJob, out spawnChunkHandle);
            var       spawnJob    = new SpawnGhostJob
            {
                spawnChunks       = spawnChunks,
                serialSpawnChunks = m_SerialSpawnChunks,
                entityType        = entityType,
                serializers       = serializers,
                freeGhostIds      = m_FreeGhostIds,
                allocatedGhostIds = m_AllocatedGhostIds,
                commandBuffer     = commandBuffer
            };

            inputDeps = spawnJob.Schedule(JobHandle.CombineDependencies(inputDeps, spawnChunkHandle));
            // This was the last job using the commandBuffer
            m_Barrier.AddJobHandleForProducer(inputDeps);

            JobHandle despawnChunksHandle, ghostChunksHandle;
            var       despawnChunks = ghostDespawnGroup.CreateArchetypeChunkArray(Allocator.TempJob, out despawnChunksHandle);
            var       ghostChunks   = ghostGroup.CreateArchetypeChunkArray(Allocator.TempJob, out ghostChunksHandle);

            inputDeps = JobHandle.CombineDependencies(inputDeps, despawnChunksHandle, ghostChunksHandle);

            var serialDep = new NativeArray <JobHandle>(m_ConnectionStates.Count + 1, Allocator.Temp);

            // In case there are 0 connections
            serialDep[0] = inputDeps;
            for (int con = 0; con < m_ConnectionStates.Count; ++con)
            {
                var connectionEntity       = m_ConnectionStates[con].Entity;
                var chunkSerializationData = m_ConnectionStates[con].SerializationState;
                var serializeJob           = new SerializeJob
                {
                    driver                 = m_ReceiveSystem.ConcurrentDriver,
                    unreliablePipeline     = m_ReceiveSystem.UnreliablePipeline,
                    despawnChunks          = despawnChunks,
                    ghostChunks            = ghostChunks,
                    connectionEntity       = connectionEntity,
                    chunkSerializationData = chunkSerializationData,
                    ackFromEntity          = GetComponentDataFromEntity <NetworkSnapshotAckComponent>(true),
                    connectionFromEntity   = GetComponentDataFromEntity <NetworkStreamConnection>(true),
                    serialSpawnChunks      = m_SerialSpawnChunks,
                    entityType             = entityType,
                    ghostSystemStateType   = ghostSystemStateType,
                    serializers            = serializers,
                    compressionModel       = m_CompressionModel,
                    currentTick            = currentTick,
                    localTime              = NetworkTimeSystem.TimestampMS
                };
                // FIXME: disable safety for BufferFromEntity is not working
                serialDep[con + 1] = serializeJob.Schedule(serialDep[con]);
            }

            inputDeps = JobHandle.CombineDependencies(serialDep);

            var cleanupJob = new CleanupJob
            {
                despawnChunks     = despawnChunks,
                spawnChunks       = spawnChunks,
                ghostChunks       = ghostChunks,
                serialSpawnChunks = m_SerialSpawnChunks
            };

            inputDeps = cleanupJob.Schedule(inputDeps);

            return(inputDeps);
        }
Beispiel #2
0
        protected override void OnUpdate()
        {
            uint tick = _ghostPredictionSystemGroup.PredictingTick;

            // 新添加的ghost
            Entities.With(ghostSpawnGroup).ForEach((Entity ent, ref GhostComponent ghostComponent) =>
            {
                ++_ghostInstanceId;
                ghostComponent.Id = _ghostInstanceId;
                PostUpdateCommands.AddComponent(ent, new GhostSystemStateComponent {
                    ghostId = ghostComponent.Id
                });
                _newGhosts.Add(ghostComponent.Id, ent);
            });

            ClientServerTickRate tickRate = default;

            if (HasSingleton <ClientServerTickRate>())
            {
                tickRate = GetSingleton <ClientServerTickRate>();
            }

            tickRate.ResolveDefaults();
            int networkTickInterval = tickRate.SimulationTickRate / tickRate.NetworkTickRate;

            if (tick % networkTickInterval != 0)
            {
                return;
            }

            var localTime = NetworkTimeSystem.TimestampMS;

            // 需要发送快照的ghost chunk
            // 已经按照原型分块了
            NativeArray <ArchetypeChunk> ghostChunks =
                ghostGroup.CreateArchetypeChunkArrayAsync(Allocator.TempJob, out JobHandle ghostChunksHandle);
            NativeArray <ArchetypeChunk> despawnChunks =
                ghostDespawnGroup.CreateArchetypeChunkArrayAsync(Allocator.TempJob, out JobHandle despawnChunksHandle);

            JobHandle.CompleteAll(ref ghostChunksHandle, ref despawnChunksHandle);

            var connections = connectionGroup.ToEntityArray(Allocator.TempJob);

            // 获取动态组件类型
            var ghostSerializerCollectionSystem = World.GetExistingSystem <GhostCollectionSystem>();

            for (int i = 0; i < connections.Length; i++)
            {
                SerializeJob serializeJob = new SerializeJob
                {
                    ConnectionEntity     = connections[i],
                    ConnectionFromEntity = GetComponentDataFromEntity <NetworkStreamConnection>(),
                    AckFromEntity        = GetComponentDataFromEntity <NetworkSnapshotAckComponent>(),
                    LocalTime            = localTime,
                    Tick                       = tick,
                    NetDriver                  = _driver.ToConcurrent(),
                    CompressionModel           = _compressionModel,
                    UnreliablePipeline         = _unreliablePipeline,
                    GhostChunks                = ghostChunks,
                    DespawnChunks              = despawnChunks,
                    EntityTypeHandle           = GetEntityTypeHandle(),
                    GhostTypeHandle            = GetComponentTypeHandle <GhostComponent>(),
                    GhostSystemStateTypeHandle = GetComponentTypeHandle <GhostSystemStateComponent>(),
                    GhostTypeCollection        = ghostSerializerCollectionSystem.GhostTypeCollection,
                    GhostComponentIndex        = ghostSerializerCollectionSystem.IndexCollection,
                    GhostComponentSerializers  = ghostSerializerCollectionSystem.Serializers,
                };

                // FIXME
                var listLength = ghostSerializerCollectionSystem.Serializers.Length;
                if (listLength <= 32)
                {
                    var dynamicListJob = new SerializeJob32 {
                        Job = serializeJob
                    };
                    DynamicTypeList.PopulateList(this, ghostSerializerCollectionSystem.Serializers, true,
                                                 ref dynamicListJob.List);

                    dynamicListJob.Schedule().Complete();
                }
            }


            // 移除的ghost
            Entities.With(ghostDespawnGroup).ForEach((Entity ent, ref GhostSystemStateComponent state) =>
            {
                _newGhosts.Remove(state.ghostId);
                PostUpdateCommands.RemoveComponent <GhostSystemStateComponent>(ent);
            });

            connections.Dispose();
            ghostChunks.Dispose();
            despawnChunks.Dispose();
        }