public void Execute(DynamicComponentTypeHandle *ghostChunkComponentTypesPtr, int ghostChunkComponentTypesLength) { for (int i = 0; i < GhostChunks.Length; i++) { ArchetypeChunk chunk = GhostChunks[i]; var entities = chunk.GetNativeArray(EntityTypeHandle); var buffers = chunk.GetBufferAccessor(SnapshotBufferTypeHandle); var datas = chunk.GetNativeArray(SnapshotComponentTypeHandle); var ghosts = chunk.GetNativeArray(GhostComponentTypeHandle); for (int ent = 0; ent < entities.Length; ent++) { GhostComponent ghostComponent = ghosts[ent]; var typeState = GhostTypeCollection[ghostComponent.GhostType]; SnapshotData snapshotData = datas[ent]; DynamicBuffer <SnapshotDataBuffer> snapshotDataBuffer = buffers[ent]; if (snapshotData.SnapshotSize == 0) { continue; } bool isGet = snapshotData.GetDataAtTick(snapshotDataBuffer, InterpolatedTargetTick, InterpolatedTargetTickFraction, out var dataAtTick); int baseOffset = typeState.FirstComponent; int numBaseComponents = typeState.NumComponents; // 跳过Tick int offset = GlobalConstants.TickSize; for (int j = 0; j < numBaseComponents; j++) { int compIdx = ComponentIndex[baseOffset + j].ComponentIndex; GhostComponentSerializer serializer = ComponentSerializers[compIdx]; DynamicComponentTypeHandle dynamicType = ghostChunkComponentTypesPtr[compIdx]; if (chunk.Has(dynamicType)) { IntPtr compPtr = (IntPtr)chunk .GetDynamicComponentDataArrayReinterpret <byte>(dynamicType, serializer.ComponentSize).GetUnsafePtr(); if (isGet) { serializer.CopyFromSnapshot.Ptr.Invoke( compPtr + serializer.ComponentSize * ent, (IntPtr)(&dataAtTick), offset); } } offset += serializer.DataSize; } } } }
protected override unsafe void OnUpdate() { var session = GetSingletonEntity <CommandTargetComponent>(); var inBuffer = EntityManager.GetBuffer <IncomingSnapshotDataStreamBufferComponent>(session); var reader = inBuffer.AsDataStreamReader(); if (reader.Length == 0) { return; } #if UNITY_EDITOR || DEVELOPMENT_BUILD NetDebug.SnapMS = reader.Length; NetDebug.DownCount += reader.Length; #endif uint serverTick = reader.ReadUInt(); var ack = EntityManager.GetComponentData <NetworkSnapshotAckComponent>(session); if (ack.IsOldWithLastReceivedSnapshotByLocal(serverTick)) { return; } ack.UpdateLocalValues(serverTick); PostUpdateCommands.SetComponent(session, ack); uint destroyLen = reader.ReadUInt(); uint len = reader.ReadUInt(); for (int i = 0; i < destroyLen; i++) { int ghostId = reader.ReadPackedInt(_networkCompressionModel); if (!_ghostEntityMap.TryGetValue(ghostId, out Entity ent)) { continue; } var s = new GhostDespawnSystem.DelayedDespawnGhost { Ghost = new SpawnedGhost { GhostId = ghostId, SpawnTick = EntityManager.GetComponentData <GhostComponent>(ent).SpawnTick }, Tick = serverTick }; _ghostEntityMap.Remove(ghostId); if (EntityManager.HasComponent <GhostPredictionComponent>(ent)) { _ghostDespawnSystem.AddToPredicted(s); } else { _ghostDespawnSystem.AddToInterpolated(s); } } var ghostSerializerCollectionSystem = World.GetExistingSystem <GhostCollectionSystem>(); var ghostSpawnEntity = GetSingletonEntity <GhostSpawnQueueComponent>(); var bufferFromEntity = GetBufferFromEntity <SnapshotDataBuffer>(); var spawnBufferFromEntity = GetBufferFromEntity <GhostSpawnBuffer>(); var compFromEntity = GetComponentDataFromEntity <SnapshotData>(); for (int i = 0; i < len; i++) { int ghostType = reader.ReadPackedInt(_networkCompressionModel); int ghostId = reader.ReadPackedInt(_networkCompressionModel); if (ghostType < 0 || ghostType >= ghostSerializerCollectionSystem.GhostTypeCollection.Length) { throw new Exception($"GhostRecvSystem:GhostType={ghostType}, GhostId={ghostId}"); } // 序列化组件信息 var typeState = ghostSerializerCollectionSystem.GhostTypeCollection[ghostType]; var baseOffset = typeState.FirstComponent; var numBaseComponents = typeState.NumComponents; byte *snapshotData; DynamicBuffer <SnapshotDataBuffer> snapshotDataBuffer; SnapshotData snapshotDataComponent; bool existingGhost = _ghostEntityMap.TryGetValue(ghostId, out Entity gent); if (existingGhost && bufferFromEntity.HasComponent(gent) && compFromEntity.HasComponent(gent)) { snapshotDataBuffer = bufferFromEntity[gent]; snapshotData = (byte *)snapshotDataBuffer.GetUnsafePtr(); snapshotDataComponent = compFromEntity[gent]; snapshotDataComponent.LatestIndex = (snapshotDataComponent.LatestIndex + 1) % GlobalConstants.SnapshotHistorySize; compFromEntity[gent] = snapshotDataComponent; } else { var ghostSpawnBuffer = spawnBufferFromEntity[ghostSpawnEntity]; snapshotDataBuffer = bufferFromEntity[ghostSpawnEntity]; var snapshotDataBufferOffset = snapshotDataBuffer.Length; ghostSpawnBuffer.Add(new GhostSpawnBuffer { GhostType = ghostType, GhostId = ghostId, ClientSpawnTick = serverTick, ServerSpawnTick = serverTick, DataOffset = snapshotDataBufferOffset }); snapshotDataBuffer.ResizeUninitialized(snapshotDataBufferOffset + typeState.SnapshotSize); snapshotData = (byte *)snapshotDataBuffer.GetUnsafePtr() + snapshotDataBufferOffset; UnsafeUtility.MemClear(snapshotData, typeState.SnapshotSize); snapshotDataComponent = new SnapshotData { SnapshotSize = typeState.SnapshotSize, LatestIndex = 0 }; } // 把快照放到对应内存中 snapshotData += typeState.SnapshotSize * snapshotDataComponent.LatestIndex; *((uint *)snapshotData) = serverTick; snapshotData += GlobalConstants.TickSize; // 放到快照对应内存位置 for (int j = 0; j < numBaseComponents; j++) { var compIdx = ghostSerializerCollectionSystem.IndexCollection[baseOffset + j].ComponentIndex; var serializer = ghostSerializerCollectionSystem.Serializers[compIdx]; serializer.Deserialize.Ptr.Invoke((IntPtr)snapshotData, ref reader, ref _networkCompressionModel); snapshotData += serializer.DataSize; } } #if UNITY_EDITOR || DEVELOPMENT_BUILD NetDebug.Set(nameof(ack.LastReceivedSnapshotByLocal), ack.LastReceivedSnapshotByLocal); NetDebug.Set(nameof(ack.EstimatedRTT), ack.EstimatedRTT); NetDebug.Set(nameof(ack.DeviationRTT), ack.DeviationRTT); NetDebug.RTT = (uint)ack.EstimatedRTT; NetDebug.Jitter = (uint)ack.DeviationRTT; #endif inBuffer.Clear(); }
public void Execute(DynamicComponentTypeHandle *ghostChunkComponentTypesPtr, int ghostChunkComponentTypesLength) { for (int i = 0; i < GhostChunks.Length; i++) { ArchetypeChunk chunk = GhostChunks[i]; var entities = chunk.GetNativeArray(EntityTypeHandle); var buffers = chunk.GetBufferAccessor(SnapshotBufferTypeHandle); var datas = chunk.GetNativeArray(SnapshotComponentTypeHandle); var ghosts = chunk.GetNativeArray(GhostComponentTypeHandle); for (int ent = 0; ent < entities.Length; ent++) { GhostComponent ghostComponent = ghosts[ent]; var typeState = GhostTypeCollection[ghostComponent.GhostType]; SnapshotData snapshotData = datas[ent]; DynamicBuffer <SnapshotDataBuffer> snapshotDataBuffer = buffers[ent]; if (snapshotData.SnapshotSize == 0) { continue; } IntPtr latestSnapshot = snapshotData.GetLatest(snapshotDataBuffer); int baseOffset = typeState.FirstComponent; int numBaseComponents = typeState.NumComponents; // 跳过Tick int offset = GlobalConstants.TickSize; for (int j = 0; j < numBaseComponents; j++) { int cmpIdx = ComponentIndex[baseOffset + j].ComponentIndex; var serializer = ComponentSerializers[cmpIdx]; DynamicComponentTypeHandle dynamicType = ghostChunkComponentTypesPtr[cmpIdx]; if (chunk.Has(dynamicType)) { IntPtr compPtr = (IntPtr)chunk .GetDynamicComponentDataArrayReinterpret <byte>(dynamicType, serializer.ComponentSize).GetUnsafePtr(); // 不回滚只更新值 if (serializer.IsUpdateValue) { var dataAtTick = new SnapshotData.DataAtTick { Tick = snapshotData.GetLatestTick(snapshotDataBuffer), InterpolationFactor = 1, SnapshotAfter = latestSnapshot, SnapshotBefore = latestSnapshot }; serializer.CopyFromSnapshot.Ptr.Invoke( compPtr + serializer.ComponentSize * ent, (IntPtr)(&dataAtTick), offset); } else { serializer.RestoreFromBackup.Ptr.Invoke( compPtr + serializer.ComponentSize * ent, latestSnapshot + offset); } } offset += serializer.DataSize; } } } }