public static void AddCommandData <T>(this DynamicBuffer <T> commandArray, T commandData) where T : struct, ICommandData <T> { uint targetTick = commandData.Tick; int oldestIdx = 0; uint oldestTick = 0; for (int i = 0; i < commandArray.Length; ++i) { uint tick = commandArray[i].Tick; if (tick == targetTick) { // Already exists, replace it commandArray[i] = commandData; return; } if (oldestTick == 0 || SequenceHelpers.IsNewer(oldestTick, tick)) { oldestIdx = i; oldestTick = tick; } } if (commandArray.Length < k_CommandDataMaxSize) { commandArray.Add(commandData); } else { commandArray[oldestIdx] = commandData; } }
public void Execute([ReadOnly] DynamicBuffer <TSnapshot> snapshots, ref TComponent component, ref Predicted <TSnapshot> predictedData, ref GhostPredictedComponent globalPredicted) { snapshots.GetDataAtTick(targetTick, out var snapshotData); var lastPredictedTickInst = lastPredictTick; if (lastPredictedTickInst == 0 || predictedData.AppliedTick != snapshotData.Tick) { lastPredictedTickInst = snapshotData.Tick; } else if (!SequenceHelpers.IsNewer(lastPredictedTickInst, snapshotData.Tick)) { lastPredictedTickInst = snapshotData.Tick; } if (minPredictedTick[ThreadIndex] == 0 || SequenceHelpers.IsNewer(minPredictedTick[ThreadIndex], lastPredictedTickInst)) { minPredictedTick[ThreadIndex] = lastPredictedTickInst; } predictedData = new Predicted <TSnapshot> { AppliedTick = snapshotData.Tick, PredictionStartTick = lastPredictedTickInst }; globalPredicted.AppliedTick = predictedData.AppliedTick; globalPredicted.PredictionStartTick = predictedData.PredictionStartTick; if (lastPredictedTickInst != snapshotData.Tick) { return; } snapshotData.SynchronizeTo(ref component, jobData); }
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 void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex) { var deserializerState = new GhostDeserializerState { GhostMap = GhostMap }; var ghostEntityArray = chunk.GetNativeArray(ghostEntityType); var ghostSnapshotDataArray = chunk.GetBufferAccessor(ghostSnapshotDataType); var ghostHealthArray = chunk.GetNativeArray(ghostHealthType); var ghostPlayerUnitArray = chunk.GetNativeArray(ghostPlayerUnitType); var ghostUnitSelectionStateArray = chunk.GetNativeArray(ghostUnitSelectionStateType); var ghostLinkedEntityGroupArray = chunk.GetBufferAccessor(ghostLinkedEntityGroupType); #if UNITY_EDITOR || DEVELOPMENT_BUILD var minMaxOffset = ThreadIndex * (JobsUtility.CacheLineSize / 4); #endif for (int entityIndex = 0; entityIndex < ghostEntityArray.Length; ++entityIndex) { var snapshot = ghostSnapshotDataArray[entityIndex]; #if UNITY_EDITOR || DEVELOPMENT_BUILD var latestTick = snapshot.GetLatestTick(); if (latestTick != 0) { if (minMaxSnapshotTick[minMaxOffset] == 0 || SequenceHelpers.IsNewer(minMaxSnapshotTick[minMaxOffset], latestTick)) { minMaxSnapshotTick[minMaxOffset] = latestTick; } if (minMaxSnapshotTick[minMaxOffset + 1] == 0 || SequenceHelpers.IsNewer(latestTick, minMaxSnapshotTick[minMaxOffset + 1])) { minMaxSnapshotTick[minMaxOffset + 1] = latestTick; } } #endif _UnitSnapshotData snapshotData; snapshot.GetDataAtTick(targetTick, targetTickFraction, out snapshotData); var ghostHealth = ghostHealthArray[entityIndex]; var ghostPlayerUnit = ghostPlayerUnitArray[entityIndex]; var ghostUnitSelectionState = ghostUnitSelectionStateArray[entityIndex]; var ghostRotation = ghostRotationFromEntity[ghostLinkedEntityGroupArray[entityIndex][0].Value]; var ghostTranslation = ghostTranslationFromEntity[ghostLinkedEntityGroupArray[entityIndex][0].Value]; var ghostChild0Rotation = ghostRotationFromEntity[ghostLinkedEntityGroupArray[entityIndex][1].Value]; var ghostChild0Translation = ghostTranslationFromEntity[ghostLinkedEntityGroupArray[entityIndex][1].Value]; ghostHealth.Value = snapshotData.GetHealthValue(deserializerState); ghostPlayerUnit.PlayerId = snapshotData.GetPlayerUnitPlayerId(deserializerState); ghostPlayerUnit.UnitId = snapshotData.GetPlayerUnitUnitId(deserializerState); ghostUnitSelectionState.IsSelected = snapshotData.GetUnitSelectionStateIsSelected(deserializerState); ghostRotation.Value = snapshotData.GetRotationValue(deserializerState); ghostTranslation.Value = snapshotData.GetTranslationValue(deserializerState); ghostChild0Rotation.Value = snapshotData.GetChild0RotationValue(deserializerState); ghostChild0Translation.Value = snapshotData.GetChild0TranslationValue(deserializerState); ghostRotationFromEntity[ghostLinkedEntityGroupArray[entityIndex][0].Value] = ghostRotation; ghostTranslationFromEntity[ghostLinkedEntityGroupArray[entityIndex][0].Value] = ghostTranslation; ghostRotationFromEntity[ghostLinkedEntityGroupArray[entityIndex][1].Value] = ghostChild0Rotation; ghostTranslationFromEntity[ghostLinkedEntityGroupArray[entityIndex][1].Value] = ghostChild0Translation; ghostHealthArray[entityIndex] = ghostHealth; ghostPlayerUnitArray[entityIndex] = ghostPlayerUnit; ghostUnitSelectionStateArray[entityIndex] = ghostUnitSelectionState; } }
public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex) { var deserializerState = new GhostDeserializerState { GhostMap = GhostMap }; var ghostEntityArray = chunk.GetNativeArray(ghostEntityType); var ghostSnapshotDataArray = chunk.GetBufferAccessor(ghostSnapshotDataType); #if UNITY_EDITOR || DEVELOPMENT_BUILD var minMaxOffset = ThreadIndex * (JobsUtility.CacheLineSize / 4); #endif for (int entityIndex = 0; entityIndex < ghostEntityArray.Length; ++entityIndex) { var snapshot = ghostSnapshotDataArray[entityIndex]; #if UNITY_EDITOR || DEVELOPMENT_BUILD var latestTick = snapshot.GetLatestTick(); if (latestTick != 0) { if (minMaxSnapshotTick[minMaxOffset] == 0 || SequenceHelpers.IsNewer(minMaxSnapshotTick[minMaxOffset], latestTick)) { minMaxSnapshotTick[minMaxOffset] = latestTick; } if (minMaxSnapshotTick[minMaxOffset + 1] == 0 || SequenceHelpers.IsNewer(latestTick, minMaxSnapshotTick[minMaxOffset + 1])) { minMaxSnapshotTick[minMaxOffset + 1] = latestTick; } } #endif LobbyConnectionGhostSnapshotData snapshotData; snapshot.GetDataAtTick(targetTick, targetTickFraction, out snapshotData); } }
public void Execute() { var keys = predictionSpawnCleanupMap.GetKeyArray(Allocator.Temp); for (var i = 0; i < keys.Length; ++i) { predictionSpawnGhosts[keys[i]] = default(PredictSpawnGhost); } for (int i = 0; i < predictionSpawnGhosts.Length; ++i) { if (predictionSpawnGhosts[i].entity != Entity.Null && SequenceHelpers.IsNewer(interpolationTarget, predictionSpawnGhosts[i].snapshotData.Tick)) { // Trigger a delete of the entity commandBuffer.RemoveComponent(predictionSpawnGhosts[i].entity, ghostComponentType); predictionSpawnGhosts[i] = default(PredictSpawnGhost); } if (predictionSpawnGhosts[i].entity == Entity.Null) { predictionSpawnGhosts.RemoveAtSwapBack(i); --i; } } }
protected override void OnUpdate() { //This is the NetCode recommended method to identify predicted spawning for player spawned objects //More information can be found at: https://docs.unity3d.com/Packages/[email protected]/manual/ghost-snapshots.html //under "Entity spawning" var spawnListEntity = GetSingletonEntity <PredictedGhostSpawnList>(); var spawnListFromEntity = GetBufferFromEntity <PredictedGhostSpawn>(); Dependency = Entities .WithAll <GhostSpawnQueueComponent>() .WithoutBurst() .ForEach((DynamicBuffer <GhostSpawnBuffer> ghosts, DynamicBuffer <SnapshotDataBuffer> data) => { var spawnList = spawnListFromEntity[spawnListEntity]; for (int i = 0; i < ghosts.Length; ++i) { var ghost = ghosts[i]; if (ghost.SpawnType == GhostSpawnBuffer.Type.Predicted) { for (int j = 0; j < spawnList.Length; ++j) { if (ghost.GhostType == spawnList[j].ghostType && !SequenceHelpers.IsNewer(spawnList[j].spawnTick, ghost.ServerSpawnTick + 5) && SequenceHelpers.IsNewer(spawnList[j].spawnTick + 5, ghost.ServerSpawnTick)) { ghost.PredictedSpawnEntity = spawnList[j].entity; spawnList[j] = spawnList[spawnList.Length - 1]; spawnList.RemoveAt(spawnList.Length - 1); break; } } ghosts[i] = ghost; } } }).Schedule(Dependency); }
public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex) { var deserializerState = new GhostDeserializerState { GhostMap = GhostMap }; var ghostEntityArray = chunk.GetNativeArray(ghostEntityType); var ghostSnapshotDataArray = chunk.GetBufferAccessor(ghostSnapshotDataType); var ghostHealthComponentArray = chunk.GetNativeArray(ghostHealthComponentType); var ghostProgressionComponentArray = chunk.GetNativeArray(ghostProgressionComponentType); var ghostSynchronizedCarComponentArray = chunk.GetNativeArray(ghostSynchronizedCarComponentType); var ghostRotationArray = chunk.GetNativeArray(ghostRotationType); var ghostTranslationArray = chunk.GetNativeArray(ghostTranslationType); #if UNITY_EDITOR || DEVELOPMENT_BUILD var minMaxOffset = ThreadIndex * (JobsUtility.CacheLineSize / 4); #endif for (int entityIndex = 0; entityIndex < ghostEntityArray.Length; ++entityIndex) { var snapshot = ghostSnapshotDataArray[entityIndex]; #if UNITY_EDITOR || DEVELOPMENT_BUILD var latestTick = snapshot.GetLatestTick(); if (latestTick != 0) { if (minMaxSnapshotTick[minMaxOffset] == 0 || SequenceHelpers.IsNewer(minMaxSnapshotTick[minMaxOffset], latestTick)) { minMaxSnapshotTick[minMaxOffset] = latestTick; } if (minMaxSnapshotTick[minMaxOffset + 1] == 0 || SequenceHelpers.IsNewer(latestTick, minMaxSnapshotTick[minMaxOffset + 1])) { minMaxSnapshotTick[minMaxOffset + 1] = latestTick; } } #endif // If there is no data found don't apply anything (would be default state), required for prespawned ghosts CarStubSnapshotData snapshotData; if (!snapshot.GetDataAtTick(targetTick, targetTickFraction, out snapshotData)) { return; } var ghostHealthComponent = ghostHealthComponentArray[entityIndex]; var ghostProgressionComponent = ghostProgressionComponentArray[entityIndex]; var ghostSynchronizedCarComponent = ghostSynchronizedCarComponentArray[entityIndex]; var ghostRotation = ghostRotationArray[entityIndex]; var ghostTranslation = ghostTranslationArray[entityIndex]; ghostHealthComponent.Health = snapshotData.GetHealthComponentHealth(deserializerState); ghostProgressionComponent.CrossedCheckpoints = snapshotData.GetProgressionComponentCrossedCheckpoints(deserializerState); ghostSynchronizedCarComponent.PlayerId = snapshotData.GetSynchronizedCarComponentPlayerId(deserializerState); ghostSynchronizedCarComponent.SteerAngle = snapshotData.GetSynchronizedCarComponentSteerAngle(deserializerState); ghostSynchronizedCarComponent.IsShieldActive = snapshotData.GetSynchronizedCarComponentIsShieldActive(deserializerState); ghostRotation.Value = snapshotData.GetRotationValue(deserializerState); ghostTranslation.Value = snapshotData.GetTranslationValue(deserializerState); ghostHealthComponentArray[entityIndex] = ghostHealthComponent; ghostProgressionComponentArray[entityIndex] = ghostProgressionComponent; ghostSynchronizedCarComponentArray[entityIndex] = ghostSynchronizedCarComponent; ghostRotationArray[entityIndex] = ghostRotation; ghostTranslationArray[entityIndex] = ghostTranslation; } }
protected override void OnUpdate() { var spawnListEntity = GetSingletonEntity <PredictedGhostSpawnList>(); var spawnListFromEntity = GetBufferFromEntity <PredictedGhostSpawn>(); Dependency = Entities .WithAll <GhostSpawnQueueComponent>() .WithoutBurst() .ForEach((DynamicBuffer <GhostSpawnBuffer> ghosts, DynamicBuffer <SnapshotDataBuffer> data) => { var spawnList = spawnListFromEntity[spawnListEntity]; for (int i = 0; i < ghosts.Length; ++i) { var ghost = ghosts[i]; if (ghost.SpawnType == GhostSpawnBuffer.Type.Predicted) { for (int j = 0; j < spawnList.Length; ++j) { if (ghost.GhostType == spawnList[j].ghostType && !SequenceHelpers.IsNewer(spawnList[j].spawnTick, ghost.ServerSpawnTick + 5) && SequenceHelpers.IsNewer(spawnList[j].spawnTick + 5, ghost.ServerSpawnTick)) { ghost.PredictedSpawnEntity = spawnList[j].entity; spawnList[j] = spawnList[spawnList.Length - 1]; spawnList.RemoveAt(spawnList.Length - 1); break; } } ghosts[i] = ghost; } } }).Schedule(Dependency); }
public bool IsReceivedByRemote(uint tick) { if (tick == 0 || LastReceivedSnapshotByRemote == 0) { return(false); } if (SequenceHelpers.IsNewer(tick, LastReceivedSnapshotByRemote)) { return(false); } int bit = (int)(LastReceivedSnapshotByRemote - tick); if (bit >= 256) { return(false); } if (bit >= 192) { bit -= 192; return((ReceivedSnapshotByRemoteMask3 & (1ul << bit)) != 0); } if (bit >= 128) { bit -= 128; return((ReceivedSnapshotByRemoteMask2 & (1ul << bit)) != 0); } if (bit >= 64) { bit -= 64; return((ReceivedSnapshotByRemoteMask1 & (1ul << bit)) != 0); } return((ReceivedSnapshotByRemoteMask0 & (1ul << bit)) != 0); }
public static bool GetDataAtTick <T>(this DynamicBuffer <T> commandArray, uint targetTick, out T commandData) where T : struct, ICommandData <T> { int beforeIdx = 0; uint beforeTick = 0; for (int i = 0; i < commandArray.Length; ++i) { uint tick = commandArray[i].Tick; if (!SequenceHelpers.IsNewer(tick, targetTick) && (beforeTick == 0 || SequenceHelpers.IsNewer(tick, beforeTick))) { beforeIdx = i; beforeTick = tick; } } if (beforeTick == 0) { commandData = default(T); return(false); } commandData = commandArray[beforeIdx]; return(true); }
protected override void OnUpdate() { // Gather the min/max age stats var intsPerCacheLine = JobsUtility.CacheLineSize / 4; for (int i = 1; i < JobsUtility.MaxJobThreadCount; ++i) { if (m_ghostSnapshotTickMinMax[intsPerCacheLine * i] != 0 && (m_ghostSnapshotTickMinMax[0] == 0 || SequenceHelpers.IsNewer(m_ghostSnapshotTickMinMax[0], m_ghostSnapshotTickMinMax[intsPerCacheLine * i]))) { m_ghostSnapshotTickMinMax[0] = m_ghostSnapshotTickMinMax[intsPerCacheLine * i]; } if (m_ghostSnapshotTickMinMax[intsPerCacheLine * i + 1] != 0 && (m_ghostSnapshotTickMinMax[1] == 0 || SequenceHelpers.IsNewer(m_ghostSnapshotTickMinMax[intsPerCacheLine * i + 1], m_ghostSnapshotTickMinMax[1]))) { m_ghostSnapshotTickMinMax[1] = m_ghostSnapshotTickMinMax[intsPerCacheLine * i + 1]; } m_ghostSnapshotTickMinMax[intsPerCacheLine * i] = 0; m_ghostSnapshotTickMinMax[intsPerCacheLine * i + 1] = 0; } // Pass the min and max to stats collection m_GhostStatsCollectionSystem.SetSnapshotTick(m_ghostSnapshotTickMinMax[0], m_ghostSnapshotTickMinMax[1]); m_ghostSnapshotTickMinMax[0] = 0; m_ghostSnapshotTickMinMax[1] = 0; base.OnUpdate(); }
public void UpdateReceivedByRemote(uint tick, uint mask) { if (tick == 0) { ReceivedSnapshotByRemoteMask3 = 0; ReceivedSnapshotByRemoteMask2 = 0; ReceivedSnapshotByRemoteMask1 = 0; ReceivedSnapshotByRemoteMask0 = 0; LastReceivedSnapshotByRemote = 0; } else if (LastReceivedSnapshotByRemote == 0) { ReceivedSnapshotByRemoteMask3 = 0; ReceivedSnapshotByRemoteMask2 = 0; ReceivedSnapshotByRemoteMask1 = 0; ReceivedSnapshotByRemoteMask0 = mask; LastReceivedSnapshotByRemote = tick; } else if (SequenceHelpers.IsNewer(tick, LastReceivedSnapshotByRemote)) { int shamt = (int)(tick - LastReceivedSnapshotByRemote); if (shamt >= 256) { ReceivedSnapshotByRemoteMask3 = 0; ReceivedSnapshotByRemoteMask2 = 0; ReceivedSnapshotByRemoteMask1 = 0; ReceivedSnapshotByRemoteMask0 = mask; } else { while (shamt >= 64) { ReceivedSnapshotByRemoteMask3 = ReceivedSnapshotByRemoteMask2; ReceivedSnapshotByRemoteMask2 = ReceivedSnapshotByRemoteMask1; ReceivedSnapshotByRemoteMask1 = ReceivedSnapshotByRemoteMask0; ReceivedSnapshotByRemoteMask0 = 0; shamt -= 64; } if (shamt == 0) { ReceivedSnapshotByRemoteMask0 |= mask; } else { ReceivedSnapshotByRemoteMask3 = (ReceivedSnapshotByRemoteMask3 << shamt) | (ReceivedSnapshotByRemoteMask2 >> (64 - shamt)); ReceivedSnapshotByRemoteMask2 = (ReceivedSnapshotByRemoteMask2 << shamt) | (ReceivedSnapshotByRemoteMask1 >> (64 - shamt)); ReceivedSnapshotByRemoteMask1 = (ReceivedSnapshotByRemoteMask1 << shamt) | (ReceivedSnapshotByRemoteMask0 >> (64 - shamt)); ReceivedSnapshotByRemoteMask0 = (ReceivedSnapshotByRemoteMask0 << shamt) | mask; } } LastReceivedSnapshotByRemote = tick; } }
public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex) { var deserializerState = new GhostDeserializerState { GhostMap = GhostMap }; var ghostEntityArray = chunk.GetNativeArray(ghostEntityType); var ghostSnapshotDataArray = chunk.GetBufferAccessor(ghostSnapshotDataType); var ghostCameraRigChildArray = chunk.GetNativeArray(ghostCameraRigChildType); var ghostPilotDataArray = chunk.GetNativeArray(ghostPilotDataType); var ghostRotationArray = chunk.GetNativeArray(ghostRotationType); var ghostTranslationArray = chunk.GetNativeArray(ghostTranslationType); #if UNITY_EDITOR || DEVELOPMENT_BUILD var minMaxOffset = ThreadIndex * (JobsUtility.CacheLineSize / 4); #endif for (int entityIndex = 0; entityIndex < ghostEntityArray.Length; ++entityIndex) { var snapshot = ghostSnapshotDataArray[entityIndex]; #if UNITY_EDITOR || DEVELOPMENT_BUILD var latestTick = snapshot.GetLatestTick(); if (latestTick != 0) { if (minMaxSnapshotTick[minMaxOffset] == 0 || SequenceHelpers.IsNewer(minMaxSnapshotTick[minMaxOffset], latestTick)) { minMaxSnapshotTick[minMaxOffset] = latestTick; } if (minMaxSnapshotTick[minMaxOffset + 1] == 0 || SequenceHelpers.IsNewer(latestTick, minMaxSnapshotTick[minMaxOffset + 1])) { minMaxSnapshotTick[minMaxOffset + 1] = latestTick; } } #endif // If there is no data found don't apply anything (would be default state), required for prespawned ghosts PilotSnapshotData snapshotData; if (!snapshot.GetDataAtTick(targetTick, targetTickFraction, out snapshotData)) { return; } var ghostCameraRigChild = ghostCameraRigChildArray[entityIndex]; var ghostPilotData = ghostPilotDataArray[entityIndex]; var ghostRotation = ghostRotationArray[entityIndex]; var ghostTranslation = ghostTranslationArray[entityIndex]; ghostCameraRigChild.headPose = snapshotData.GetCameraRigChildheadPose(deserializerState); ghostCameraRigChild.headRot = snapshotData.GetCameraRigChildheadRot(deserializerState); ghostCameraRigChild.leftHandPose = snapshotData.GetCameraRigChildleftHandPose(deserializerState); ghostCameraRigChild.leftHandRot = snapshotData.GetCameraRigChildleftHandRot(deserializerState); ghostCameraRigChild.rightHandPose = snapshotData.GetCameraRigChildrightHandPose(deserializerState); ghostCameraRigChild.rightHandRot = snapshotData.GetCameraRigChildrightHandRot(deserializerState); ghostPilotData.PlayerId = snapshotData.GetPilotDataPlayerId(deserializerState); ghostRotation.Value = snapshotData.GetRotationValue(deserializerState); ghostTranslation.Value = snapshotData.GetTranslationValue(deserializerState); ghostCameraRigChildArray[entityIndex] = ghostCameraRigChild; ghostPilotDataArray[entityIndex] = ghostPilotData; ghostRotationArray[entityIndex] = ghostRotation; ghostTranslationArray[entityIndex] = ghostTranslation; } }
public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex) { var deserializerState = new GhostDeserializerState { GhostMap = GhostMap }; var ghostEntityArray = chunk.GetNativeArray(ghostEntityType); var ghostSnapshotDataArray = chunk.GetBufferAccessor(ghostSnapshotDataType); var ghostPlayerStateArray = chunk.GetNativeArray(ghostPlayerStateType); #if UNITY_EDITOR || DEVELOPMENT_BUILD var minMaxOffset = ThreadIndex * (JobsUtility.CacheLineSize / 4); #endif for (int entityIndex = 0; entityIndex < ghostEntityArray.Length; ++entityIndex) { var snapshot = ghostSnapshotDataArray[entityIndex]; #if UNITY_EDITOR || DEVELOPMENT_BUILD var latestTick = snapshot.GetLatestTick(); if (latestTick != 0) { if (minMaxSnapshotTick[minMaxOffset] == 0 || SequenceHelpers.IsNewer(minMaxSnapshotTick[minMaxOffset], latestTick)) { minMaxSnapshotTick[minMaxOffset] = latestTick; } if (minMaxSnapshotTick[minMaxOffset + 1] == 0 || SequenceHelpers.IsNewer(latestTick, minMaxSnapshotTick[minMaxOffset + 1])) { minMaxSnapshotTick[minMaxOffset + 1] = latestTick; } } #endif PlayerStateSnapshotData snapshotData; snapshot.GetDataAtTick(targetTick, targetTickFraction, out snapshotData); var ghostPlayerState = ghostPlayerStateArray[entityIndex]; ghostPlayerState.playerId = snapshotData.GetPlayerStateplayerId(deserializerState); ghostPlayerState.playerName = snapshotData.GetPlayerStateplayerName(deserializerState); ghostPlayerState.teamIndex = snapshotData.GetPlayerStateteamIndex(deserializerState); ghostPlayerState.score = snapshotData.GetPlayerStatescore(deserializerState); ghostPlayerState.gameModeSystemInitialized = snapshotData.GetPlayerStategameModeSystemInitialized(deserializerState); ghostPlayerState.displayCountDown = snapshotData.GetPlayerStatedisplayCountDown(deserializerState); ghostPlayerState.countDown = snapshotData.GetPlayerStatecountDown(deserializerState); ghostPlayerState.displayScoreBoard = snapshotData.GetPlayerStatedisplayScoreBoard(deserializerState); ghostPlayerState.displayGameScore = snapshotData.GetPlayerStatedisplayGameScore(deserializerState); ghostPlayerState.displayGameResult = snapshotData.GetPlayerStatedisplayGameResult(deserializerState); ghostPlayerState.gameResult = snapshotData.GetPlayerStategameResult(deserializerState); ghostPlayerState.displayGoal = snapshotData.GetPlayerStatedisplayGoal(deserializerState); ghostPlayerState.goalPosition = snapshotData.GetPlayerStategoalPosition(deserializerState); ghostPlayerState.goalDefendersColor = snapshotData.GetPlayerStategoalDefendersColor(deserializerState); ghostPlayerState.goalAttackersColor = snapshotData.GetPlayerStategoalAttackersColor(deserializerState); ghostPlayerState.goalAttackers = snapshotData.GetPlayerStategoalAttackers(deserializerState); ghostPlayerState.goalDefenders = snapshotData.GetPlayerStategoalDefenders(deserializerState); ghostPlayerState.goalString = snapshotData.GetPlayerStategoalString(deserializerState); ghostPlayerState.actionString = snapshotData.GetPlayerStateactionString(deserializerState); ghostPlayerState.goalCompletion = snapshotData.GetPlayerStategoalCompletion(deserializerState); ghostPlayerStateArray[entityIndex] = ghostPlayerState; } }
public void UpdateRemoteTime(uint remoteTime, uint localTimeMinusRTT, uint localTime) { if (remoteTime != 0 && SequenceHelpers.IsNewer(remoteTime, LastReceivedRemoteTime)) { LastReceivedRemoteTime = remoteTime; LastReceivedRTT = localTime - localTimeMinusRTT; LastReceiveTimestamp = localTime; } }
// This is updated on both server and client side, used to track RTT on both sides. // It is updated when receiving command or snapshot. // // public void UpdateRemoteTime(uint remoteTime, uint localTimeMinusRTT, uint localTime) // TODO: LZ: // to be confirmed: fix RTT calculation: // A B // t0: A send time // T0: B receive time // T1: B send time // t1: A receive time public void UpdateRemoteTime(uint remoteTime, uint localSentPlusRomoteProcess, uint localTime) { if (remoteTime != 0 && SequenceHelpers.IsNewer(remoteTime, LastReceivedRemoteTime)) { LastReceivedRemoteTime = remoteTime; LastReceivedRTT = localTime - localSentPlusRomoteProcess; // t1 - (t0 + (T1 - T0)) LastReceiveTimestamp = localTime; } }
public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex) { var deserializerState = new GhostDeserializerState { GhostMap = GhostMap }; var ghostEntityArray = chunk.GetNativeArray(ghostEntityType); var ghostSnapshotDataArray = chunk.GetBufferAccessor(ghostSnapshotDataType); var predictedGhostComponentArray = chunk.GetNativeArray(predictedGhostComponentType); #if UNITY_EDITOR || DEVELOPMENT_BUILD var minMaxOffset = ThreadIndex * (JobsUtility.CacheLineSize / 4); #endif for (int entityIndex = 0; entityIndex < ghostEntityArray.Length; ++entityIndex) { var snapshot = ghostSnapshotDataArray[entityIndex]; #if UNITY_EDITOR || DEVELOPMENT_BUILD var latestTick = snapshot.GetLatestTick(); if (latestTick != 0) { if (minMaxSnapshotTick[minMaxOffset] == 0 || SequenceHelpers.IsNewer(minMaxSnapshotTick[minMaxOffset], latestTick)) { minMaxSnapshotTick[minMaxOffset] = latestTick; } if (minMaxSnapshotTick[minMaxOffset + 1] == 0 || SequenceHelpers.IsNewer(latestTick, minMaxSnapshotTick[minMaxOffset + 1])) { minMaxSnapshotTick[minMaxOffset + 1] = latestTick; } } #endif SpawnerSnapshotData snapshotData; snapshot.GetDataAtTick(targetTick, out snapshotData); var predictedData = predictedGhostComponentArray[entityIndex]; var lastPredictedTickInst = lastPredictedTick; if (lastPredictedTickInst == 0 || predictedData.AppliedTick != snapshotData.Tick) { lastPredictedTickInst = snapshotData.Tick; } else if (!SequenceHelpers.IsNewer(lastPredictedTickInst, snapshotData.Tick)) { lastPredictedTickInst = snapshotData.Tick; } if (minPredictedTick[ThreadIndex] == 0 || SequenceHelpers.IsNewer(minPredictedTick[ThreadIndex], lastPredictedTickInst)) { minPredictedTick[ThreadIndex] = lastPredictedTickInst; } predictedGhostComponentArray[entityIndex] = new PredictedGhostComponent { AppliedTick = snapshotData.Tick, PredictionStartTick = lastPredictedTickInst }; if (lastPredictedTickInst != snapshotData.Tick) { continue; } } }
public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex) { var deserializerState = new GhostDeserializerState { GhostMap = GhostMap }; var ghostEntityArray = chunk.GetNativeArray(ghostEntityType); var ghostSnapshotDataArray = chunk.GetBufferAccessor(ghostSnapshotDataType); var ghostPlayerDataArray = chunk.GetNativeArray(ghostPlayerDataType); var ghostRotationArray = chunk.GetNativeArray(ghostRotationType); var ghostTranslationArray = chunk.GetNativeArray(ghostTranslationType); #if UNITY_EDITOR || DEVELOPMENT_BUILD var minMaxOffset = ThreadIndex * (JobsUtility.CacheLineSize / 4); #endif for (int entityIndex = 0; entityIndex < ghostEntityArray.Length; ++entityIndex) { var snapshot = ghostSnapshotDataArray[entityIndex]; #if UNITY_EDITOR || DEVELOPMENT_BUILD var latestTick = snapshot.GetLatestTick(); if (latestTick != 0) { if (minMaxSnapshotTick[minMaxOffset] == 0 || SequenceHelpers.IsNewer(minMaxSnapshotTick[minMaxOffset], latestTick)) { minMaxSnapshotTick[minMaxOffset] = latestTick; } if (minMaxSnapshotTick[minMaxOffset + 1] == 0 || SequenceHelpers.IsNewer(latestTick, minMaxSnapshotTick[minMaxOffset + 1])) { minMaxSnapshotTick[minMaxOffset + 1] = latestTick; } } #endif SphereSnapshotData snapshotData; snapshot.GetDataAtTick(targetTick, targetTickFraction, out snapshotData); var ghostPlayerData = ghostPlayerDataArray[entityIndex]; var ghostRotation = ghostRotationArray[entityIndex]; var ghostTranslation = ghostTranslationArray[entityIndex]; ghostPlayerData.playerId = snapshotData.GetPlayerDataplayerId(deserializerState); ghostPlayerData.maxHealth = snapshotData.GetPlayerDatamaxHealth(deserializerState); ghostPlayerData.currentHealth = snapshotData.GetPlayerDatacurrentHealth(deserializerState); ghostPlayerData.death = snapshotData.GetPlayerDatadeath(deserializerState); ghostPlayerData.auto = snapshotData.GetPlayerDataauto(deserializerState); ghostPlayerData.autoSpawn = snapshotData.GetPlayerDataautoSpawn(deserializerState); ghostPlayerData.dest = snapshotData.GetPlayerDatadest(deserializerState); ghostPlayerData.dest2 = snapshotData.GetPlayerDatadest2(deserializerState); ghostPlayerData.killedBy = snapshotData.GetPlayerDatakilledBy(deserializerState); ghostPlayerData.killedByID = snapshotData.GetPlayerDatakilledByID(deserializerState); ghostRotation.Value = snapshotData.GetRotationValue(deserializerState); ghostTranslation.Value = snapshotData.GetTranslationValue(deserializerState); ghostPlayerDataArray[entityIndex] = ghostPlayerData; ghostRotationArray[entityIndex] = ghostRotation; ghostTranslationArray[entityIndex] = ghostTranslation; } }
public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex) { var deserializerState = new GhostDeserializerState { GhostMap = GhostMap }; var ghostEntityArray = chunk.GetNativeArray(ghostEntityType); var ghostSnapshotDataArray = chunk.GetBufferAccessor(ghostSnapshotDataType); #region __GHOST_INTERPOLATED_COMPONENT_ARRAY__ var ghost__GHOST_COMPONENT_TYPE_NAME__Array = chunk.GetNativeArray(ghost__GHOST_COMPONENT_TYPE_NAME__Type); #endregion #region __GHOST_INTERPOLATED_BUFFER_ARRAY__ var ghost__GHOST_COMPONENT_TYPE_NAME__Array = chunk.GetBufferAccessor(ghost__GHOST_COMPONENT_TYPE_NAME__Type); #endregion #if UNITY_EDITOR || DEVELOPMENT_BUILD var minMaxOffset = ThreadIndex * (JobsUtility.CacheLineSize / 4); #endif for (int entityIndex = 0; entityIndex < ghostEntityArray.Length; ++entityIndex) { var snapshot = ghostSnapshotDataArray[entityIndex]; #if UNITY_EDITOR || DEVELOPMENT_BUILD var latestTick = snapshot.GetLatestTick(); if (latestTick != 0) { if (minMaxSnapshotTick[minMaxOffset] == 0 || SequenceHelpers.IsNewer(minMaxSnapshotTick[minMaxOffset], latestTick)) { minMaxSnapshotTick[minMaxOffset] = latestTick; } if (minMaxSnapshotTick[minMaxOffset + 1] == 0 || SequenceHelpers.IsNewer(latestTick, minMaxSnapshotTick[minMaxOffset + 1])) { minMaxSnapshotTick[minMaxOffset + 1] = latestTick; } } #endif __GHOST_NAME__SnapshotData snapshotData; snapshot.GetDataAtTick(targetTick, targetTickFraction, out snapshotData); #region __GHOST_INTERPOLATED_BEGIN_ASSIGN__ var ghost__GHOST_COMPONENT_TYPE_NAME__ = ghost__GHOST_COMPONENT_TYPE_NAME__Array[entityIndex]; #endregion #region __GHOST_INTERPOLATED_BEGIN_ASSIGN_CHILD__ var ghost__GHOST_COMPONENT_TYPE_NAME__ = ghost__GHOST_COMPONENT_FROM_ENTITY_NAME__FromEntity[ghostLinkedEntityGroupArray[entityIndex][__GHOST_ENTITY_INDEX__].Value]; #endregion #region __GHOST_INTERPOLATED_ASSIGN__ ghost__GHOST_COMPONENT_TYPE_NAME__.__GHOST_FIELD_NAME__ = snapshotData.Get__GHOST_COMPONENT_TYPE_NAME____GHOST_FIELD_NAME__(deserializerState); #endregion #region __GHOST_INTERPOLATED_END_ASSIGN_CHILD__ ghost__GHOST_COMPONENT_FROM_ENTITY_NAME__FromEntity[ghostLinkedEntityGroupArray[entityIndex][__GHOST_ENTITY_INDEX__].Value] = ghost__GHOST_COMPONENT_TYPE_NAME__; #endregion #region __GHOST_INTERPOLATED_END_ASSIGN__ ghost__GHOST_COMPONENT_TYPE_NAME__Array[entityIndex] = ghost__GHOST_COMPONENT_TYPE_NAME__; #endregion } }
public static bool GetDataAtTick <T>(this DynamicBuffer <T> snapshotArray, uint targetTick, float targetTickFraction, out T snapshotData) where T : struct, ISnapshotData <T> { int beforeIdx = 0; uint beforeTick = 0; int afterIdx = 0; uint afterTick = 0; // If last tick is fractional before should not include the tick we are targeting, it should instead be included in after if (targetTickFraction < 1) { --targetTick; } for (int i = 0; i < snapshotArray.Length; ++i) { uint tick = snapshotArray[i].Tick; if (!SequenceHelpers.IsNewer(tick, targetTick) && (beforeTick == 0 || SequenceHelpers.IsNewer(tick, beforeTick))) { beforeIdx = i; beforeTick = tick; } if (SequenceHelpers.IsNewer(tick, targetTick) && (afterTick == 0 || SequenceHelpers.IsNewer(afterTick, tick))) { afterIdx = i; afterTick = tick; } } if (beforeTick == 0) { snapshotData = default(T); return(false); } snapshotData = snapshotArray[beforeIdx]; if (afterTick == 0) { return(true); } var after = snapshotArray[afterIdx]; float afterWeight = (float)(targetTick - beforeTick) / (float)(afterTick - beforeTick); if (targetTickFraction < 1) { afterWeight += targetTickFraction / (float)(afterTick - beforeTick); } snapshotData.Interpolate(ref after, afterWeight); return(true); }
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 Execute(Entity entity, int index, ref GhostSystemStateComponent ghost) { uint ackedByAllTick = tick[0]; if (ghost.despawnTick == 0) { ghost.despawnTick = currentTick; } else if (ackedByAllTick != 0 && !SequenceHelpers.IsNewer(ghost.despawnTick, ackedByAllTick)) { freeGhostIds.Enqueue(ghost.ghostId); commandBuffer.RemoveComponent(index, entity, ghostStateType); } }
public void UpdateReceivedByRemote(uint tick) { if (tick == 0) { LastReceivedSnapshotByRemote = 0; } else if (LastReceivedSnapshotByRemote == 0) { LastReceivedSnapshotByRemote = tick; } else if (SequenceHelpers.IsNewer(tick, LastReceivedSnapshotByRemote)) { LastReceivedSnapshotByRemote = tick; } }
public void Execute([ReadOnly] ref NetworkSnapshotAckComponent ack) { uint ackedByAllTick = tick[0]; var snapshot = ack.LastReceivedSnapshotByRemote; if (snapshot == 0) { ackedByAllTick = 0; } else if (ackedByAllTick != 0 && SequenceHelpers.IsNewer(ackedByAllTick, snapshot)) { ackedByAllTick = snapshot; } tick[0] = ackedByAllTick; }
public void GetCollisionWorldFromTick(uint tick, uint interpolationDelay, out CollisionWorld collWorld) { // Clamp to oldest physics copy when requesting older data than supported if (interpolationDelay > m_size - 1) { interpolationDelay = (uint)m_size - 1; } tick -= interpolationDelay; if (SequenceHelpers.IsNewer(tick, m_lastStoredTick)) { tick = m_lastStoredTick; } var index = (int)(tick % m_size); GetCollisionWorldFromIndex(index, out collWorld); }
public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex) { GhostDeserializerState deserializerState = new GhostDeserializerState { GhostMap = GhostMap }; NativeArray <Entity> ghostEntityArray = chunk.GetNativeArray(ghostEntityType); BufferAccessor <NetCodePlayModeTestGhostObjectSnapshotData> ghostSnapshotDataArray = chunk.GetBufferAccessor(ghostSnapshotDataType); NativeArray <Rotation> ghostRotationArray = chunk.GetNativeArray(ghostRotationType); NativeArray <Translation> ghostTranslationArray = chunk.GetNativeArray(ghostTranslationType); #if UNITY_EDITOR || DEVELOPMENT_BUILD int minMaxOffset = ThreadIndex * (JobsUtility.CacheLineSize / 4); #endif for (int entityIndex = 0; entityIndex < ghostEntityArray.Length; ++entityIndex) { DynamicBuffer <NetCodePlayModeTestGhostObjectSnapshotData> snapshot = ghostSnapshotDataArray[entityIndex]; #if UNITY_EDITOR || DEVELOPMENT_BUILD uint latestTick = snapshot.GetLatestTick(); if (latestTick != 0) { if (minMaxSnapshotTick[minMaxOffset] == 0 || SequenceHelpers.IsNewer(minMaxSnapshotTick[minMaxOffset], latestTick)) { minMaxSnapshotTick[minMaxOffset] = latestTick; } if (minMaxSnapshotTick[minMaxOffset + 1] == 0 || SequenceHelpers.IsNewer(latestTick, minMaxSnapshotTick[minMaxOffset + 1])) { minMaxSnapshotTick[minMaxOffset + 1] = latestTick; } } #endif NetCodePlayModeTestGhostObjectSnapshotData snapshotData; snapshot.GetDataAtTick(targetTick, targetTickFraction, out snapshotData); Rotation ghostRotation = ghostRotationArray[entityIndex]; Translation ghostTranslation = ghostTranslationArray[entityIndex]; ghostRotation.Value = snapshotData.GetRotationValue(deserializerState); ghostTranslation.Value = snapshotData.GetTranslationValue(deserializerState); ghostRotationArray[entityIndex] = ghostRotation; ghostTranslationArray[entityIndex] = ghostTranslation; } }
protected override void OnUpdate() { if (_isServer) { this.PredictingTick = World.GetExistingSystem <ServerSimulationSystemGroup>().Tick; NetDebug.ServerTick = this.PredictingTick; base.OnUpdate(); return; } //==================================================================================== IsFixError = false; NetworkSnapshotAckComponent ack = GetSingleton <NetworkSnapshotAckComponent>(); uint targetTick = _tickSimulationSystemGroup.ServerTick; if (!SequenceHelpers.IsNewer(targetTick, ack.LastReceivedSnapshotByLocal)) { return; } if (!SequenceHelpers.IsNewer(ack.LastReceivedSnapshotByLocal, LastAppliedSnapshotTick)) { LitUpdate(targetTick); return; } LastAppliedSnapshotTick = ack.LastReceivedSnapshotByLocal; if (targetTick - LastAppliedSnapshotTick > GlobalConstants.CommandDataMaxSize) { LastAppliedSnapshotTick = targetTick - GlobalConstants.CommandDataMaxSize; } IsRewind = true; // Debug.Log($"开始回滚:{LastAppliedSnapshotTick + 1} to {targetTick}, PredictingTick={PredictingTick}"); for (uint i = LastAppliedSnapshotTick + 1; i != targetTick; ++i) { LitUpdate(i); } IsRewind = false; // Debug.Log($"回滚结束:{PredictingTick}"); IsFixError = true; LitUpdate(targetTick); }
public void UpdateRemoteTime(uint remoteTime, uint localTimeMinusRTT, uint localTime) { if (remoteTime != 0 && SequenceHelpers.IsNewer(remoteTime, LastReceivedRemoteTime)) { LastReceivedRemoteTime = remoteTime; LastReceiveTimestamp = localTime; uint lastReceivedRTT = localTime - localTimeMinusRTT; if (EstimatedRTT == 0) { EstimatedRTT = lastReceivedRTT; } else { EstimatedRTT = EstimatedRTT * 0.875f + lastReceivedRTT * 0.125f; } DeviationRTT = DeviationRTT * 0.75f + math.abs(lastReceivedRTT - EstimatedRTT) * 0.25f; } }
public static uint GetLatestTick <T>(this DynamicBuffer <T> snapshotArray) where T : struct, ISnapshotData <T> { if (snapshotArray.Length == 0) { return(0); } var tick = snapshotArray[0].Tick; for (int i = 1; i < snapshotArray.Length; ++i) { if (SequenceHelpers.IsNewer(snapshotArray[i].Tick, tick)) { tick = snapshotArray[i].Tick; } } return(tick); }