private static void Postfix() { if (MPClientExtrapolation.bodies_to_resolve.Count == 0 /* && MPClientExtrapolation.players_to_resolve.Count == 0 */) { return; } var amount = MPClientExtrapolation.GetWeaponExtrapolationTime(); if (amount <= 0f) { return; } //foreach (var kvp in MPClientExtrapolation.players_to_resolve) { // var player = kvp.Key; // var velocities = kvp.Value; // player.c_player_ship.c_transform.localPosition = velocities.LocalPosition; // player.c_player_ship.c_transform.rotation = velocities.Rotation; // player.c_player_ship.c_mesh_collider_trans.localPosition = player.c_player_ship.c_transform.localPosition; //} NetworkSim.PauseAllRigidBodiesExcept(null); foreach (var body in MPClientExtrapolation.bodies_to_resolve) { if (NetworkSim.m_paused_rigid_bodies.ContainsKey(body)) { var state = NetworkSim.m_paused_rigid_bodies[body]; body.isKinematic = false; body.velocity = state.m_velocity; body.angularVelocity = state.m_angular_velocity; } } //foreach (var kvp in MPClientExtrapolation.players_to_resolve) { // var player = kvp.Key; // var velocities = kvp.Value; // player.c_player_ship.c_rigidbody.isKinematic = false; // player.c_player_ship.c_rigidbody.velocity = velocities.Velocity; // player.c_player_ship.c_rigidbody.angularVelocity = velocities.AngularVelocity; // player.c_player_ship.c_rigidbody.drag = 0f; //} Physics.Simulate(amount); //foreach (var kvp in MPClientExtrapolation.players_to_resolve) { // var player = kvp.Key; // var velocities = kvp.Value; // player.c_player_ship.c_rigidbody.isKinematic = false; // player.c_player_ship.c_rigidbody.velocity = Vector3.zero; // player.c_player_ship.c_rigidbody.angularVelocity = Vector3.zero; // player.c_player_ship.c_rigidbody.drag = velocities.Drag; //} NetworkSim.ResumeAllPausedRigidBodies(); MPClientExtrapolation.bodies_to_resolve.Clear(); //MPClientExtrapolation.players_to_resolve.Clear(); }
private static void Postfix() { MPClientExtrapolation.InitForMatch(); }
// Called per frame, moves ships along their interpolation/extrapolation motions public static void updatePlayerPositions() { float now = Time.time; // needs to be the same time source we use for m_last_update_time NewPlayerSnapshotToClientMessage msgA = null; // interpolation: start NewPlayerSnapshotToClientMessage msgB = null; // interpolation: end, extrapolation start float interpolate_factor = 0.0f; // interpolation: factor in [0,1] float delta_t = 0.0f; int interpolate_ticks = 0; bool do_interpolation = false; // find out which case we have, and get the relevant snapshot message(s) lock (m_last_messages_lock) { /* * for (int xxx=0; xxx<m_last_messages_ring_count; xxx++) { * Debug.LogFormat("having snapshot from {0} represents {1}", m_last_messages_ring[(m_last_messages_ring_pos_last + 4 - xxx)&3].m_timestamp, m_last_update_time - xxx* Time.fixedDeltaTime); * } */ if (m_last_messages_ring_count < 1) { // we do not have any snapshot messages... return; } // make sure m_last_update_time is up-to-date ResyncTime(); // NOTE: now and m_last_update_time indirectly have timeScale already applied, as they are based on Time.time // we need to adjust just the ping and the mms_ship_max_interpolate_frames offset... // Also note that the server still sends the unscaled velocities. delta_t = now + Time.timeScale * MPClientExtrapolation.GetShipExtrapolationTime() - m_last_update_time; // if we want interpolation, add this as a _negative_ offset // we use delta_t=0 as the base for from which we extrapolate into the future delta_t -= (Menus.mms_lag_compensation_ship_added_lag / 1000f) * Time.timeScale; // it might sound absurd, but after this point, the Time.fixedDeltaTime is correct // and MUST NOT be scaled by timeScale. The data packets do contain 16.67ms of // movement each, we already have taken the time dilation into account above... // time difference in physics ticks float delta_ticks = delta_t / Time.fixedDeltaTime; // the number of frames we need to interpolate into // <= 0 means no interpolation at all, // 1 would mean we use the second most recent and the most recent snapshot, and so on... interpolate_ticks = -(int)Mathf.Floor(delta_ticks); // do we need to do interpolation? do_interpolation = (interpolate_ticks > 0); if (do_interpolation) { // we need interpolate_ticks + 1 elements in the ring buffer // NOTE: in the code below, the index [(m_last_messages_ring_pos_last + 4 - i) &3] // effectively acceses the i-ith most recent element (i starting by 0) // since 4-(i-1) == 4-i+ 1 = 5-i, 5-i references the next older one if (interpolate_ticks < m_last_messages_ring_count) { msgA = m_last_messages_ring[(m_last_messages_ring_pos_last + 4 - interpolate_ticks) & 3]; msgB = m_last_messages_ring[(m_last_messages_ring_pos_last + 5 - interpolate_ticks) & 3]; interpolate_factor = delta_ticks - Mathf.Floor(delta_ticks); } else { // not enough packets received so far // "extrapolate" into the past do_interpolation = false; // get the oldest snapshot we have msgB = m_last_messages_ring[(m_last_messages_ring_pos_last + 5 - m_last_messages_ring_count) & 3]; // offset the time for the extrapolation // delta_t is currently relative to the most recent element we have, // but we need it relative to msgA delta_t += Time.fixedDeltaTime * (m_last_messages_ring_count - 1); } } else { // extrapolation case // use the most recently received snapshot msgB = m_last_messages_ring[m_last_messages_ring_pos_last]; } } // lock m_last_frame_time = now; /* * Debug.LogFormat("At: {0} Setting: {1} IntFrames: {2}, dt: {3}, IntFact {4}",now,Menus.mms_ship_max_interpolate_frames, interpolate_ticks, delta_t, interpolate_factor); * if (interpolate_ticks > 0) { * Debug.LogFormat("Using A from {0}", msgA.m_timestamp); * Debug.LogFormat("Using B from {0}", msgB.m_timestamp); * } else { * Debug.LogFormat("Using B from {0}", msgB.m_timestamp); * } */ // keep statistics m_compensation_sum += delta_t; m_compensation_count++; // NOTE: one can't replace(interpolate_ticks > 0) by do_interpolation here, // because even in the (interpolate_ticks > 0) case the code above could // have reset do_interpolation to false because we technically want // the "extrapolation" into the past thing, but we don't want to count that // as extrapolation... m_compensation_interpol_count += (interpolate_ticks > 0)?1:0; if (Time.time >= m_compensation_last + 5.0 && m_compensation_count > 0) { // Debug.LogFormat("ship lag compensation over last {0} frames: {1}ms / {2} physics ticks, {3} interpolation ({4}%) packets: {5} received / {6} missing / {7} old ignored", // m_compensation_count, 1000.0f* (m_compensation_sum/ m_compensation_count), // (m_compensation_sum/m_compensation_count)/Time.fixedDeltaTime, // m_compensation_interpol_count, // 100.0f*((float)m_compensation_interpol_count/(float)m_compensation_count), // m_received_packets_count, m_missing_packets_count, m_ignored_packets_count); m_compensation_sum = 0.0f; m_compensation_count = 0; m_compensation_interpol_count = 0; m_received_packets_count = 0; m_missing_packets_count = 0; m_ignored_packets_count = 0; m_compensation_last = Time.time; } // actually apply the operation to each player foreach (Player player in Overload.NetworkManager.m_Players) { if (player != null && !player.isLocalPlayer && !player.m_spectator) { // do the actual interpolation or extrapolation, as calculated above if (do_interpolation) { NewPlayerSnapshot A = GetPlayerSnapshot(msgA, player); NewPlayerSnapshot B = GetPlayerSnapshot(msgB, player); if (A != null && B != null) { interpolatePlayer(player, A, B, interpolate_factor); } } else { NewPlayerSnapshot snapshot = GetPlayerSnapshot(msgB, player); if (snapshot != null) { extrapolatePlayer(player, snapshot, delta_t); } } } } }