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:
+23
-25
@@ -22,8 +22,8 @@ namespace MSCO
|
|||||||
public int OwnerId = NoOwner;
|
public int OwnerId = NoOwner;
|
||||||
public bool OwnerActive; // Besitzer hält/fährt es gerade aktiv
|
public bool OwnerActive; // Besitzer hält/fährt es gerade aktiv
|
||||||
public bool WasKinematic; // Zustand bevor ein anderer Spieler es übernommen hat
|
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
|
// Gelenke der angebauten Teile, solange ein anderer das Fahrzeug fährt: unzerbrechlich (vorherige Bruchkraft/-moment)
|
||||||
public Dictionary<Rigidbody, bool> FrozenParts;
|
public Dictionary<Joint, Vector2> HeldJoints;
|
||||||
public float NextPartScan;
|
public float NextPartScan;
|
||||||
public float StillTime;
|
public float StillTime;
|
||||||
public float NoMotionClaimUntil; // kurz nach einer Übergabe nicht wegen Nachfedern/Nachrollen übernehmen
|
public float NoMotionClaimUntil; // kurz nach einer Übergabe nicht wegen Nachfedern/Nachrollen übernehmen
|
||||||
@@ -305,7 +305,7 @@ namespace MSCO
|
|||||||
foreach (SyncedBody b in byId.Values)
|
foreach (SyncedBody b in byId.Values)
|
||||||
{
|
{
|
||||||
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) 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 (Time.time - b.AvatarHoldTime < 0.2f) continue; // sitzt gerade in der Hand eines Mitspielers
|
||||||
if ((b.Rb.position - b.TargetPos).sqrMagnitude > SnapDistance * SnapDistance)
|
if ((b.Rb.position - b.TargetPos).sqrMagnitude > SnapDistance * SnapDistance)
|
||||||
{
|
{
|
||||||
@@ -393,45 +393,43 @@ namespace MSCO
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Ein anderer Spieler bewegt das Objekt: bei uns nur noch folgen (kinematisch). Bei Fahrzeugen auch alle
|
/// Ein anderer Spieler bewegt das Objekt: bei uns nur noch folgen (kinematisch). Bei Fahrzeugen hängen die
|
||||||
/// angebauten Teile - die hängen in MSC mit Gelenken (mit Bruchkraft) am Auto. Würde nur das Auto ruckartig
|
/// angebauten Teile (Türen, Kotflügel, Sitze ...) mit Gelenken mit Bruchkraft am Auto. Die Teile dürfen NICHT
|
||||||
/// versetzt, rissen die Gelenke und das Auto fiele auseinander.
|
/// 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>
|
/// </summary>
|
||||||
void FreezeForRemote(SyncedBody b)
|
void FreezeForRemote(SyncedBody b)
|
||||||
{
|
{
|
||||||
b.WasKinematic = b.Rb.isKinematic;
|
b.WasKinematic = b.Rb.isKinematic;
|
||||||
b.Rb.isKinematic = true;
|
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;
|
b.NextPartScan = Time.time + 1f; // später angebaute Teile ebenfalls
|
||||||
if (b.FrozenParts == null) b.FrozenParts = new Dictionary<Rigidbody, bool>();
|
if (b.HeldJoints == null) b.HeldJoints = new Dictionary<Joint, Vector2>();
|
||||||
foreach (Rigidbody part in b.Rb.GetComponentsInChildren<Rigidbody>())
|
foreach (Joint j in b.Rb.GetComponentsInChildren<Joint>(true))
|
||||||
{
|
{
|
||||||
if (part == b.Rb || b.FrozenParts.ContainsKey(part)) continue;
|
if (j == null || b.HeldJoints.ContainsKey(j)) continue;
|
||||||
b.FrozenParts[part] = part.isKinematic;
|
b.HeldJoints[j] = new Vector2(j.breakForce, j.breakTorque);
|
||||||
part.isKinematic = true;
|
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)
|
void RestoreKinematic(SyncedBody b)
|
||||||
{
|
{
|
||||||
if (b.Rb != null) b.Rb.isKinematic = b.WasKinematic;
|
if (b.Rb != null) b.Rb.isKinematic = b.WasKinematic;
|
||||||
if (b.FrozenParts == null) return;
|
if (b.HeldJoints == null) return;
|
||||||
foreach (KeyValuePair<Rigidbody, bool> kv in b.FrozenParts)
|
foreach (KeyValuePair<Joint, Vector2> kv in b.HeldJoints)
|
||||||
{
|
{
|
||||||
if (kv.Key == null) continue;
|
if (kv.Key == null) continue; // Teil wurde inzwischen abgebaut
|
||||||
kv.Key.isKinematic = kv.Value;
|
kv.Key.breakForce = kv.Value.x;
|
||||||
if (!kv.Value)
|
kv.Key.breakTorque = kv.Value.y;
|
||||||
{
|
|
||||||
kv.Key.velocity = Vector3.zero; // keinen Schwung aus dem Folgen mitnehmen
|
|
||||||
kv.Key.angularVelocity = Vector3.zero;
|
|
||||||
}
|
}
|
||||||
}
|
b.HeldJoints = null;
|
||||||
b.FrozenParts = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SendOwnedStates()
|
void SendOwnedStates()
|
||||||
|
|||||||
+18
-2
@@ -11,7 +11,7 @@ namespace MSCO
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class Passenger
|
public class Passenger
|
||||||
{
|
{
|
||||||
const float EnterRange = 5f; // so nah muss man am Fahrzeug stehen (Abstand zur Fahrzeugmitte)
|
const float EnterRange = 3f; // so nah muss man an der Karosserie stehen
|
||||||
const float CenterSeatThreshold = 0.2f;
|
const float CenterSeatThreshold = 0.2f;
|
||||||
const float BehindCenterSeat = 0.7f;
|
const float BehindCenterSeat = 0.7f;
|
||||||
const float ExitSideOffset = 1.4f; // beim Aussteigen so weit neben den Sitz
|
const float ExitSideOffset = 1.4f; // beim Aussteigen so weit neben den Sitz
|
||||||
@@ -44,7 +44,7 @@ namespace MSCO
|
|||||||
float nearest = float.MaxValue;
|
float nearest = float.MaxValue;
|
||||||
foreach (SyncedBody b in driven)
|
foreach (SyncedBody b in driven)
|
||||||
{
|
{
|
||||||
float d = (b.Rb.worldCenterOfMass - player.position).sqrMagnitude;
|
float d = DistanceToVehicleSq(b, player.position);
|
||||||
nearest = Mathf.Min(nearest, d);
|
nearest = Mathf.Min(nearest, d);
|
||||||
PlayerInfo owner;
|
PlayerInfo owner;
|
||||||
if (!players.TryGetValue(b.OwnerId, out owner) || owner.Avatar == null) continue;
|
if (!players.TryGetValue(b.OwnerId, out owner) || owner.Avatar == null) continue;
|
||||||
@@ -69,6 +69,22 @@ namespace MSCO
|
|||||||
return "Riding as passenger (press again to get out)";
|
return "Riding as passenger (press again to get out)";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Abstand zur nächsten Stelle der Karosserie (Collider), nicht zum Schwerpunkt - den legt MSC teils weit weg,
|
||||||
|
/// dann hieß es "26 m entfernt", obwohl man direkt an der Tür stand.
|
||||||
|
/// </summary>
|
||||||
|
static float DistanceToVehicleSq(SyncedBody b, Vector3 point)
|
||||||
|
{
|
||||||
|
float best = (b.Rb.position - point).sqrMagnitude;
|
||||||
|
foreach (Collider c in b.Rb.GetComponentsInChildren<Collider>())
|
||||||
|
{
|
||||||
|
if (c == null || !c.enabled || c.isTrigger) continue;
|
||||||
|
float d = (c.bounds.ClosestPoint(point) - point).sqrMagnitude;
|
||||||
|
if (d < best) best = d;
|
||||||
|
}
|
||||||
|
return best;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>Nach der Physik (LateUpdate): Spieler auf den Sitz setzen und mitdrehen.</summary>
|
/// <summary>Nach der Physik (LateUpdate): Spieler auf den Sitz setzen und mitdrehen.</summary>
|
||||||
public void LateUpdate(Transform player, Camera cam, ObjectSync objects)
|
public void LateUpdate(Transform player, Camera cam, ObjectSync objects)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user