Performance: time-sliced checks for idle objects, fewer allocations, rarer damage checks for parked cars
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -13,6 +13,12 @@ Server und Mod müssen beide 2.8 sein (Server: `git pull && docker compose up -d
|
|||||||
- **Verkehr**: NPC-Autos fahren bei allen an derselben Stelle (der erste Spieler simuliert, die anderen folgen)
|
- **Verkehr**: NPC-Autos fahren bei allen an derselben Stelle (der erste Spieler simuliert, die anderen folgen)
|
||||||
- `vehicles` in der F7-Konsole zeigt, wie viele Karosserie-Meshes, Job-Werte und Verkehrsautos synchronisiert werden
|
- `vehicles` in der F7-Konsole zeigt, wie viele Karosserie-Meshes, Job-Werte und Verkehrsautos synchronisiert werden
|
||||||
|
|
||||||
|
**Leistung**
|
||||||
|
- Mod: herumliegende Objekte werden nur noch jedes 4. Frame geprüft (eigene/gehaltene/gefahrene weiterhin jedes Frame),
|
||||||
|
weniger Speicher-Allokationen pro Frame, Gelenke fremd gefahrener Autos seltener geprüft
|
||||||
|
- Server: Nachrichten an alle werden nur einmal verpackt; der Server wartet auf eingehende Daten statt fest zu schlafen
|
||||||
|
(geringere Verzögerung, fast keine CPU-Last im Leerlauf)
|
||||||
|
|
||||||
## 2.7
|
## 2.7
|
||||||
|
|
||||||
Server und Mod müssen beide 2.7 sein (Server: `git pull && docker compose up -d --build`).
|
Server und Mod müssen beide 2.7 sein (Server: `git pull && docker compose up -d --build`).
|
||||||
|
|||||||
+6
-2
@@ -14,7 +14,8 @@ namespace MSCO
|
|||||||
public class DamageSync
|
public class DamageSync
|
||||||
{
|
{
|
||||||
const float ScanInterval = 10f;
|
const float ScanInterval = 10f;
|
||||||
const float CheckInterval = 1f;
|
const float CheckInterval = 1f; // Fahrzeuge, die wir fahren
|
||||||
|
const float FreeCheckInterval = 5f; // geparkte Fahrzeuge (Unfall nur durch Anstoßen) seltener
|
||||||
const float MinMove = 0.002f;
|
const float MinMove = 0.002f;
|
||||||
const int MaxPerMessage = 4000;
|
const int MaxPerMessage = 4000;
|
||||||
|
|
||||||
@@ -31,7 +32,7 @@ namespace MSCO
|
|||||||
readonly Dictionary<int, DamageMesh> meshes = new Dictionary<int, DamageMesh>();
|
readonly Dictionary<int, DamageMesh> meshes = new Dictionary<int, DamageMesh>();
|
||||||
readonly HashSet<MeshFilter> seen = new HashSet<MeshFilter>();
|
readonly HashSet<MeshFilter> seen = new HashSet<MeshFilter>();
|
||||||
readonly List<int> changed = new List<int>();
|
readonly List<int> changed = new List<int>();
|
||||||
float nextScan, nextCheck;
|
float nextScan, nextCheck, nextFreeCheck;
|
||||||
static List<Type> types;
|
static List<Type> types;
|
||||||
|
|
||||||
public int Count { get { return meshes.Count; } }
|
public int Count { get { return meshes.Count; } }
|
||||||
@@ -52,12 +53,15 @@ namespace MSCO
|
|||||||
}
|
}
|
||||||
if (Time.time < nextCheck) return;
|
if (Time.time < nextCheck) return;
|
||||||
nextCheck = Time.time + CheckInterval;
|
nextCheck = Time.time + CheckInterval;
|
||||||
|
bool checkFree = Time.time >= nextFreeCheck;
|
||||||
|
if (checkFree) nextFreeCheck = Time.time + FreeCheckInterval;
|
||||||
|
|
||||||
foreach (DamageMesh m in meshes.Values)
|
foreach (DamageMesh m in meshes.Values)
|
||||||
{
|
{
|
||||||
if (m.Filter == null) continue;
|
if (m.Filter == null) continue;
|
||||||
int owner = objects.VehicleOwner(m.Root);
|
int owner = objects.VehicleOwner(m.Root);
|
||||||
if (owner != SyncedBody.NoOwner && owner != localId) continue; // der Fahrer schickt die Schäden
|
if (owner != SyncedBody.NoOwner && owner != localId) continue; // der Fahrer schickt die Schäden
|
||||||
|
if (owner == SyncedBody.NoOwner && !checkFree) continue;
|
||||||
|
|
||||||
Mesh mesh = m.Filter.sharedMesh;
|
Mesh mesh = m.Filter.sharedMesh;
|
||||||
if (mesh == null) continue;
|
if (mesh == null) continue;
|
||||||
|
|||||||
+9
-2
@@ -129,6 +129,8 @@ namespace MSCO
|
|||||||
|
|
||||||
float loadTime;
|
float loadTime;
|
||||||
float nextScan;
|
float nextScan;
|
||||||
|
int frame;
|
||||||
|
readonly List<SyncedBody> drivenList = new List<SyncedBody>();
|
||||||
float sendTimer;
|
float sendTimer;
|
||||||
|
|
||||||
FsmGameObject pickedObject;
|
FsmGameObject pickedObject;
|
||||||
@@ -191,7 +193,8 @@ namespace MSCO
|
|||||||
/// <summary>Fahrzeuge, die gerade ein anderer Spieler aktiv fährt.</summary>
|
/// <summary>Fahrzeuge, die gerade ein anderer Spieler aktiv fährt.</summary>
|
||||||
public List<SyncedBody> RemoteDrivenVehicles()
|
public List<SyncedBody> RemoteDrivenVehicles()
|
||||||
{
|
{
|
||||||
var list = new List<SyncedBody>();
|
var list = drivenList; // wird jedes Frame gebraucht: Liste wiederverwenden
|
||||||
|
list.Clear();
|
||||||
foreach (SyncedBody b in byId.Values)
|
foreach (SyncedBody b in byId.Values)
|
||||||
if (b.IsVehicle && IsRemoteOwned(b) && b.OwnerActive && b.Rb != null) list.Add(b);
|
if (b.IsVehicle && IsRemoteOwned(b) && b.OwnerActive && b.Rb != null) list.Add(b);
|
||||||
return list;
|
return list;
|
||||||
@@ -296,8 +299,12 @@ namespace MSCO
|
|||||||
bool motionClaimAllowed = Time.time - loadTime > MotionClaimGrace;
|
bool motionClaimAllowed = Time.time - loadTime > MotionClaimGrace;
|
||||||
|
|
||||||
removeList.Clear();
|
removeList.Clear();
|
||||||
|
frame++;
|
||||||
foreach (SyncedBody b in byId.Values)
|
foreach (SyncedBody b in byId.Values)
|
||||||
{
|
{
|
||||||
|
// Leistung: freie Objekte (der Großteil, meist liegen sie nur herum) nur jedes 4. Frame prüfen -
|
||||||
|
// eigene, fremde, gehaltene und gefahrene jedes Frame
|
||||||
|
if (b.OwnerId == SyncedBody.NoOwner && ((b.Id ^ frame) & 3) != 0 && b != held && b != driven) continue;
|
||||||
if (b.Rb == null)
|
if (b.Rb == null)
|
||||||
{
|
{
|
||||||
// Ganzes Objekt weg (gegessen, getrunken, verbraucht) - nicht nur der Rigidbody (Teil angebaut).
|
// Ganzes Objekt weg (gegessen, getrunken, verbraucht) - nicht nur der Rigidbody (Teil angebaut).
|
||||||
@@ -471,7 +478,7 @@ namespace MSCO
|
|||||||
|
|
||||||
void HoldParts(SyncedBody b)
|
void HoldParts(SyncedBody b)
|
||||||
{
|
{
|
||||||
b.NextPartScan = Time.time + 1f; // später angebaute Teile ebenfalls
|
b.NextPartScan = Time.time + 2f; // später angebaute Teile ebenfalls
|
||||||
if (b.HeldJoints == null) b.HeldJoints = new Dictionary<Joint, Vector2>();
|
if (b.HeldJoints == null) b.HeldJoints = new Dictionary<Joint, Vector2>();
|
||||||
foreach (Joint j in b.Rb.GetComponentsInChildren<Joint>(true))
|
foreach (Joint j in b.Rb.GetComponentsInChildren<Joint>(true))
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user