Remote-driven car: keep attached parts on unbreakable joints instead of switching them kinematic (that broke the joints and the car fell apart); passenger range measured to the car body

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-09-27 09:18:39 +02:00
co-authored by Claude Opus 5.5
parent ce4aa7e0a6
commit bdd86336c2
2 changed files with 41 additions and 27 deletions
+23 -25
View File
@@ -22,8 +22,8 @@ namespace MSCO
public int OwnerId = NoOwner;
public bool OwnerActive; // Besitzer hält/fährt es gerade aktiv
public bool WasKinematic; // Zustand bevor ein anderer Spieler es übernommen hat
// Angebaute Teile eines Fahrzeugs (eigene Rigidbodies mit Gelenken), solange ein anderer fährt: kinematisch
public Dictionary<Rigidbody, bool> FrozenParts;
// Gelenke der angebauten Teile, solange ein anderer das Fahrzeug fährt: unzerbrechlich (vorherige Bruchkraft/-moment)
public Dictionary<Joint, Vector2> HeldJoints;
public float NextPartScan;
public float StillTime;
public float NoMotionClaimUntil; // kurz nach einer Übergabe nicht wegen Nachfedern/Nachrollen übernehmen
@@ -305,7 +305,7 @@ namespace MSCO
foreach (SyncedBody b in byId.Values)
{
if (!IsRemoteOwned(b) || b.Rb == null || b.Attached) continue;
if (b.IsVehicle && Time.time >= b.NextPartScan) FreezeParts(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 ((b.Rb.position - b.TargetPos).sqrMagnitude > SnapDistance * SnapDistance)
{
@@ -393,45 +393,43 @@ namespace MSCO
}
/// <summary>
/// Ein anderer Spieler bewegt das Objekt: bei uns nur noch folgen (kinematisch). Bei Fahrzeugen auch alle
/// angebauten Teile - die hängen in MSC mit Gelenken (mit Bruchkraft) am Auto. Würde nur das Auto ruckartig
/// versetzt, rissen die Gelenke und das Auto fiele auseinander.
/// Ein anderer Spieler bewegt das Objekt: bei uns nur noch folgen (kinematisch). Bei Fahrzeugen hängen die
/// angebauten Teile (Türen, Kotflügel, Sitze ...) mit Gelenken mit Bruchkraft am Auto. Die Teile dürfen NICHT
/// selbst kinematisch geschaltet werden (das bricht die Gelenke sofort, MSC wertet es als "Teil abgefallen"),
/// und das ruckartige Folgen würde sie ebenfalls abreißen. Deshalb werden ihre Gelenke solange unzerbrechlich.
/// </summary>
void FreezeForRemote(SyncedBody b)
{
b.WasKinematic = b.Rb.isKinematic;
b.Rb.isKinematic = true;
if (b.IsVehicle) FreezeParts(b);
if (b.IsVehicle) HoldParts(b);
}
void FreezeParts(SyncedBody b)
void HoldParts(SyncedBody b)
{
b.NextPartScan = Time.time + 1f;
if (b.FrozenParts == null) b.FrozenParts = new Dictionary<Rigidbody, bool>();
foreach (Rigidbody part in b.Rb.GetComponentsInChildren<Rigidbody>())
b.NextPartScan = Time.time + 1f; // später angebaute Teile ebenfalls
if (b.HeldJoints == null) b.HeldJoints = new Dictionary<Joint, Vector2>();
foreach (Joint j in b.Rb.GetComponentsInChildren<Joint>(true))
{
if (part == b.Rb || b.FrozenParts.ContainsKey(part)) continue;
b.FrozenParts[part] = part.isKinematic;
part.isKinematic = true;
if (j == null || b.HeldJoints.ContainsKey(j)) continue;
b.HeldJoints[j] = new Vector2(j.breakForce, j.breakTorque);
j.breakForce = Mathf.Infinity;
j.breakTorque = Mathf.Infinity;
}
}
/// <summary>Wieder selbst simulieren: Auto und angebaute Teile zurück auf ihren vorherigen Zustand.</summary>
/// <summary>Wieder selbst simulieren: Auto zurück auf seinen Zustand, Gelenke wieder mit ihrer Bruchkraft.</summary>
void RestoreKinematic(SyncedBody b)
{
if (b.Rb != null) b.Rb.isKinematic = b.WasKinematic;
if (b.FrozenParts == null) return;
foreach (KeyValuePair<Rigidbody, bool> kv in b.FrozenParts)
if (b.HeldJoints == null) return;
foreach (KeyValuePair<Joint, Vector2> kv in b.HeldJoints)
{
if (kv.Key == null) continue;
kv.Key.isKinematic = kv.Value;
if (!kv.Value)
{
kv.Key.velocity = Vector3.zero; // keinen Schwung aus dem Folgen mitnehmen
kv.Key.angularVelocity = Vector3.zero;
}
if (kv.Key == null) continue; // Teil wurde inzwischen abgebaut
kv.Key.breakForce = kv.Value.x;
kv.Key.breakTorque = kv.Value.y;
}
b.FrozenParts = null;
b.HeldJoints = null;
}
void SendOwnedStates()