Smoother sync: predict remote objects/cars from their velocity, 30 updates/s for objects and players
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -28,7 +28,7 @@ namespace MSCO
|
|||||||
const float PingInterval = 2f;
|
const float PingInterval = 2f;
|
||||||
const float LateJoinSaveDelay = 1.5f; // Host: Zeit zum Speichern, bevor der Spielstand verschickt wird
|
const float LateJoinSaveDelay = 1.5f; // Host: Zeit zum Speichern, bevor der Spielstand verschickt wird
|
||||||
const float TeleportSideOffset = 1.5f; // später Beigetretene erscheinen so weit neben dem Host
|
const float TeleportSideOffset = 1.5f; // später Beigetretene erscheinen so weit neben dem Host
|
||||||
const float SendInterval = 0.05f; // 20 Updates pro Sekunde
|
const float SendInterval = 1f / 30f; // 30 Spieler-Updates pro Sekunde
|
||||||
const string PrefName = "MSCO_Name";
|
const string PrefName = "MSCO_Name";
|
||||||
const float NameTagHideDistance = 15f; // ab hier kein Namensschild mehr
|
const float NameTagHideDistance = 15f; // ab hier kein Namensschild mehr
|
||||||
const float NameTagFadeRange = 5f; // die letzten Meter davor wird es ausgeblendet
|
const float NameTagFadeRange = 5f; // die letzten Meter davor wird es ausgeblendet
|
||||||
|
|||||||
+19
-5
@@ -37,6 +37,8 @@ namespace MSCO
|
|||||||
|
|
||||||
public Vector3 TargetPos;
|
public Vector3 TargetPos;
|
||||||
public Quaternion TargetRot;
|
public Quaternion TargetRot;
|
||||||
|
public Vector3 TargetVel; // Geschwindigkeit beim Besitzer: damit wird die Position vorausberechnet
|
||||||
|
public float TargetTime; // wann TargetPos ankam
|
||||||
public float LastRecvTime;
|
public float LastRecvTime;
|
||||||
public float AvatarHoldTime = -100f; // zuletzt von der Hand eines Mitspielers platziert
|
public float AvatarHoldTime = -100f; // zuletzt von der Hand eines Mitspielers platziert
|
||||||
|
|
||||||
@@ -63,7 +65,8 @@ namespace MSCO
|
|||||||
static readonly string[] IgnoredRoots = { "PLAYER", "TRAFFIC", "NPC_CARS" };
|
static readonly string[] IgnoredRoots = { "PLAYER", "TRAFFIC", "NPC_CARS" };
|
||||||
|
|
||||||
const float MaxSmallItemMass = 60f; // schwerere Dinge ohne ITEM/PART-Tag sind Teil der Welt
|
const float MaxSmallItemMass = 60f; // schwerere Dinge ohne ITEM/PART-Tag sind Teil der Welt
|
||||||
const float SendInterval = 1f / 15f;
|
const float SendInterval = 1f / 30f; // unbewegte Objekte werden ohnehin nicht gesendet
|
||||||
|
const float MaxExtrapolation = 0.25f; // höchstens so weit (Sekunden) in die Zukunft vorausrechnen
|
||||||
const float KeepAliveInterval = 1f;
|
const float KeepAliveInterval = 1f;
|
||||||
const float ScanInterval = 3f;
|
const float ScanInterval = 3f;
|
||||||
const float FirstScanDelay = 3f;
|
const float FirstScanDelay = 3f;
|
||||||
@@ -307,15 +310,20 @@ namespace MSCO
|
|||||||
if (!IsRemoteOwned(b) || b.Rb == null || b.Attached) continue;
|
if (!IsRemoteOwned(b) || b.Rb == null || b.Attached) continue;
|
||||||
if (b.IsVehicle && Time.time >= b.NextPartScan) HoldParts(b);
|
if (b.IsVehicle && Time.time >= b.NextPartScan) HoldParts(b);
|
||||||
if (Time.time - b.AvatarHoldTime < 0.2f) continue; // sitzt gerade in der Hand eines Mitspielers
|
if (Time.time - b.AvatarHoldTime < 0.2f) continue; // sitzt gerade in der Hand eines Mitspielers
|
||||||
if ((b.Rb.position - b.TargetPos).sqrMagnitude > SnapDistance * SnapDistance)
|
// Dort, wo das Objekt beim Besitzer JETZT ungefähr ist: letzte Position + Geschwindigkeit * Alter.
|
||||||
|
// Ohne das hinken schnelle Objekte (fahrende Autos) immer einen Paketabstand hinterher und ruckeln.
|
||||||
|
float age = Mathf.Min(Time.time - b.TargetTime, MaxExtrapolation);
|
||||||
|
Vector3 predicted = b.TargetPos + b.TargetVel * age;
|
||||||
|
if ((b.Rb.position - predicted).sqrMagnitude > SnapDistance * SnapDistance)
|
||||||
{
|
{
|
||||||
b.Rb.transform.position = b.TargetPos;
|
b.Rb.transform.position = predicted;
|
||||||
b.Rb.transform.rotation = b.TargetRot;
|
b.Rb.transform.rotation = b.TargetRot;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
b.Rb.MovePosition(Vector3.Lerp(b.Rb.position, b.TargetPos, 0.35f));
|
float follow = b.IsVehicle ? 0.5f : 0.35f;
|
||||||
b.Rb.MoveRotation(Quaternion.Slerp(b.Rb.rotation, b.TargetRot, 0.35f));
|
b.Rb.MovePosition(Vector3.Lerp(b.Rb.position, predicted, follow));
|
||||||
|
b.Rb.MoveRotation(Quaternion.Slerp(b.Rb.rotation, b.TargetRot, follow));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -342,6 +350,8 @@ namespace MSCO
|
|||||||
b.Rb.transform.rotation = rot;
|
b.Rb.transform.rotation = rot;
|
||||||
b.TargetPos = pos;
|
b.TargetPos = pos;
|
||||||
b.TargetRot = rot;
|
b.TargetRot = rot;
|
||||||
|
b.TargetVel = Vector3.zero;
|
||||||
|
b.TargetTime = Time.time;
|
||||||
b.AvatarHoldTime = Time.time;
|
b.AvatarHoldTime = Time.time;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -381,6 +391,8 @@ namespace MSCO
|
|||||||
FreezeForRemote(b);
|
FreezeForRemote(b);
|
||||||
b.TargetPos = b.Rb.position;
|
b.TargetPos = b.Rb.position;
|
||||||
b.TargetRot = b.Rb.rotation;
|
b.TargetRot = b.Rb.rotation;
|
||||||
|
b.TargetVel = Vector3.zero;
|
||||||
|
b.TargetTime = Time.time;
|
||||||
}
|
}
|
||||||
b.OwnerId = ownerId;
|
b.OwnerId = ownerId;
|
||||||
}
|
}
|
||||||
@@ -492,6 +504,8 @@ namespace MSCO
|
|||||||
SetRemote(b, from, b.OwnerId == from && b.OwnerActive);
|
SetRemote(b, from, b.OwnerId == from && b.OwnerActive);
|
||||||
b.TargetPos = pos;
|
b.TargetPos = pos;
|
||||||
b.TargetRot = rot;
|
b.TargetRot = rot;
|
||||||
|
b.TargetVel = vel.sqrMagnitude < 90f * 90f ? vel : Vector3.zero;
|
||||||
|
b.TargetTime = Time.time;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user