internal void Reset() { _physicsGameTime.Reset(TimeSpan.Zero); SimulationTickNumber = default; CurrentTickTimeElapsed = TimeSpan.Zero; TotalTime = TimeSpan.Zero; }
internal static ref MovementSnapshotsComponent.MovementData CreateNewSnapshotData( FastList <MovementSnapshotsComponent.MovementData> predictedMovements, SimulationTickNumber simulationTickNumber, MovementSnapshotsComponent movementSnapshotsComponent, TransformComponent transformComponent) { predictedMovements.Add(default);
public FindSnapshotResult TryFindSnapshotClosestEqualOrLessThan(SimulationTickNumber simTickNumber) { bool isFound = false; var closestSimTickNo = new SimulationTickNumber(0); int closestIndex = -1; for (int i = 0; i < _snapshotRingBuffer.Count; i++) { var curSimTickNo = _snapshotRingBuffer[i].SimulationTickNumber; if (simTickNumber == curSimTickNo) { return(new FindSnapshotResult(_snapshotRingBuffer, i)); } else if (curSimTickNo < simTickNumber && curSimTickNo > closestSimTickNo) { isFound = true; closestSimTickNo = curSimTickNo; closestIndex = i; } } if (isFound) { return(new FindSnapshotResult(_snapshotRingBuffer, closestIndex)); } else { return(FindSnapshotResult.NotFound); } }
public static SimulationTickNumber CalculateSimulationTickNumber(TimeSpan totalTime) { // This always rounds down. var simTickNo = new SimulationTickNumber(totalTime.Ticks / GameConfig.PhysicsFixedTimeStep.Ticks); return(simTickNo); }
public static TimeSpan CalculateTickTimeElapsed(TimeSpan totalTime, SimulationTickNumber simulationTickNumber) { var simTickTime = TimeSpan.FromTicks(simulationTickNumber * GameConfig.PhysicsFixedTimeStep.Ticks); var timeElapsed = totalTime - simTickTime; return(timeElapsed); }
internal void SendClientInputPredictionsToServer(SimulationTickNumber currentSimTickNumber, NetworkMessageWriter networkMessageWriter) { for (int playerIdx = 0; playerIdx < _localPlayers.Count; playerIdx++) { ref var player = ref _localPlayers.Items[playerIdx]; var inputSnapshotsComp = player.InputSnapshotsComponent; PlayerUpdateMessage playerUpdateMsg = default; var pendingInputs = inputSnapshotsComp.PendingInputs; // Need to limit the number of input, eg. if there's a large delay in server ack response, // then most likely it has lost some of our older input. Probably should be a config setting? const int MaxPendingPlayerInputs = GameConfig.PhysicsSimulationRate * 20; // 20s worth of input const int MaxSendPlayerInputs = 10; // We will only send 10 inputs max in a single packet, and accept the fact that older inputs may be lost if (pendingInputs.Count >= MaxPendingPlayerInputs) { pendingInputs.RemoveRange(0, pendingInputs.Count - MaxPendingPlayerInputs + 1); } // Append the latest input var findSnapshotResult = inputSnapshotsComp.SnapshotStore.TryFindSnapshot(currentSimTickNumber); Debug.Assert(findSnapshotResult.IsFound); pendingInputs.Add(findSnapshotResult.Result); int sendInputCount = Math.Min(pendingInputs.Count, MaxSendPlayerInputs); // At most, only send the last 10 inputs (ie. the current inputs) to not blow out the packet size. int inputIndexOffset = pendingInputs.Count - sendInputCount; for (int i = 0; i < sendInputCount; i++) { int inputIndex = i + inputIndexOffset; if (pendingInputs[inputIndex].PlayerInputSequenceNumber > inputSnapshotsComp.ServerLastAcknowledgedPlayerInputSequenceNumber) { inputIndexOffset += i; sendInputCount -= i; break; } } networkMessageWriter.Reset(); playerUpdateMsg.AcknowledgedServerSimulationTickNumber = player.NetworkEntityComponent.LastAcknowledgedServerSimulationTickNumber; playerUpdateMsg.WriteTo(networkMessageWriter); PlayerUpdateInputMessage playerUpdateInputsMsg = default; playerUpdateInputsMsg.WriteHeader(networkMessageWriter, (ushort)sendInputCount); for (int i = 0; i < sendInputCount; i++) { int inputIndex = i + inputIndexOffset; ref var curInputData = ref pendingInputs.Items[inputIndex]; playerUpdateInputsMsg.PlayerInputSequenceNumber = curInputData.PlayerInputSequenceNumber; playerUpdateInputsMsg.MoveInput = curInputData.MoveInput; playerUpdateInputsMsg.JumpRequestedInput = curInputData.IsJumpButtonDown; playerUpdateInputsMsg.WriteNextArrayItem(networkMessageWriter); #if DEBUG //if (curInputData.MoveInput.LengthSquared() > 0) //{ // _networkEntityProcessor.DebugWriteLine($"Cln SendInput Move: {curInputData.MoveInput} - PISeqNo: {curInputData.PlayerInputSequenceNumber}"); //} #endif }
private static void SetPlayerTransform( SimulationTickNumber simulationTickNumber, MovementSnapshotsComponent movementSnapshotsComponent, CharacterComponent characterComponent, ref Vector3 position, ref Quaternion rotation) { Debug.Assert(movementSnapshotsComponent != null); ref var movementData = ref movementSnapshotsComponent.SnapshotStore.GetOrCreate(simulationTickNumber);
public ref T GetOrCreate(SimulationTickNumber simTickNumber) { var findResult = TryFindSnapshot(simTickNumber); if (findResult.IsFound) { return(ref findResult.Result); } else { _snapshotRingBuffer.Add(default);
public bool Read(out SimulationTickNumber value) { if (_reader.TryGetLong(out var innerValue)) { value = new SimulationTickNumber(innerValue); return(true); } value = default; return(false); }
public FindSnapshotResult TryFindSnapshot(SimulationTickNumber simTickNumber) { var matcher = new MatchEqualToSimNumber(simTickNumber); bool isFound = _snapshotRingBuffer.TryFindLastIndex(matcher, out int index); if (isFound) { return(new FindSnapshotResult(_snapshotRingBuffer, index)); } else { return(FindSnapshotResult.NotFound); } }
private Entity CreateAndAddClientPlayerEntity( SimulationTickNumber simulationTickNumber, SerializableGuid playerId, string playerName, ref Vector3 position, ref Quaternion rotation, bool isLocalEntity) { var gameplayScene = _lazyLoadedScene.GetGameplayScene(); var assetDefinitions = _lazyLoadedScene.GetNetworkAssetDefinitions(); Debug.Assert(!_networkEntityIdToEntityDataMap.ContainsKey(playerId)); var networkEntityId = playerId; var prefabUrl = isLocalEntity ? assetDefinitions.PlayerAssets.ClientLocalPlayer : assetDefinitions.PlayerAssets.ClientRemotePlayer; var prefab = _content.Load(prefabUrl); var clientPlayerEntities = prefab.InstantiateClientPlayer(); var playerEntity = clientPlayerEntities.PlayerEntity; var networkPlayerComp = playerEntity.Get <NetworkPlayerComponent>(); networkPlayerComp.PlayerName = playerName; var networkEntityComp = playerEntity.Get <NetworkEntityComponent>(); networkEntityComp.NetworkEntityId = networkEntityId; networkEntityComp.OwnerClientId = playerId; networkEntityComp.AssetId = _networkAssetDatabase.GetAssetIdFromUrlReference(prefabUrl); AddAndRegisterEntity(playerEntity, gameplayScene, simulationTickNumber); // Set initial position var data = _networkEntityIdToEntityDataMap[networkEntityId]; var movementSnapshotsComp = data.MovementSnapshotsComponent; var characterComp = data.CharacterComponent; SetPlayerTransform(simulationTickNumber, movementSnapshotsComp, characterComp, ref position, ref rotation); // The 'viewable' player is added separately var playerViewEntity = clientPlayerEntities.PlayerViewEntity; gameplayScene.Entities.Add(playerViewEntity); return(playerEntity); }
public FindSnapshotResult TryFindSnapshotClosestAnyDirection(SimulationTickNumber simTickNumber) { bool isFound = false; var closestSimTickNoGreater = new SimulationTickNumber(long.MaxValue); int closestIndexGreater = -1; var closestSimTickNoLesser = new SimulationTickNumber(0); int closestIndexLesser = -1; for (int i = 0; i < _snapshotRingBuffer.Count; i++) { var curSimTickNo = _snapshotRingBuffer[i].SimulationTickNumber; if (simTickNumber == curSimTickNo) { return(new FindSnapshotResult(_snapshotRingBuffer, i)); } if (curSimTickNo > simTickNumber && curSimTickNo < closestSimTickNoGreater) { isFound = true; closestSimTickNoGreater = curSimTickNo; closestIndexGreater = i; } if (curSimTickNo < simTickNumber && curSimTickNo > closestSimTickNoLesser) { isFound = true; closestSimTickNoLesser = curSimTickNo; closestIndexLesser = i; } } if (isFound) { if ((closestSimTickNoGreater - simTickNumber) < (simTickNumber - closestSimTickNoLesser)) { return(new FindSnapshotResult(_snapshotRingBuffer, closestIndexGreater)); } else { return(new FindSnapshotResult(_snapshotRingBuffer, closestIndexLesser)); } } else { return(FindSnapshotResult.NotFound); } }
private static void CreateNewSnapshotData( SnapshotStore <InputSnapshotsComponent.InputCommandSet> snapshotStore, SimulationTickNumber simulationTickNumber, PlayerInputSequenceNumber nextPlayerInputSequenceNumber) { ref var inputSet = ref snapshotStore.GetOrCreate(simulationTickNumber, out bool wasCreated);
public void SetClockFromTickNumber(SimulationTickNumber simulationTickNumber) { LastServerSimulationTickNumber = simulationTickNumber; CurrentTickTimeElapsed = TimeSpan.Zero; TargetTotalTime = TimeSpan.FromTicks(simulationTickNumber * GameConfig.PhysicsFixedTimeStep.Ticks); }