Unsichtbare Spieler Bug und Desynchronisation virtueller Welten beheben

Eine technische Analyse des Unsichtbare-Spieler-Glitches sowie der Desynchronisation virtueller Welten in SA:MP/CRMP-Servern inklusive eines sicheren Teleportations-Algorithmus.

20.05.2026 Deutsch

Unsichtbare Spieler Bug und Desynchronisation virtueller Welten beheben

Einer der ältesten und frustrierendsten Glitches auf SA:MP/CRMP-Servern ist das Auftreten von sogenannten "unsichtbaren Spielern". Ein Benutzer betritt ein Interieur, spawnt oder teleportiert sich zu einem Event, kann jedoch andere Teilnehmer, benutzerdefinierte Mapping-Objekte (Wände, Türen, Möbel) oder Fahrzeuge nicht sehen. Das Ganze passiert, obwohl Server-Logs und die Admin-Sicht bestätigen, dass er sich am korrekten Ort befindet. Umgekehrt kann ein Spieler von einem unsichtbaren Gegner getötet werden, der auf einem anderen Bildschirm direkt vor ihm steht.

Im Kern dieses Fehlers liegt eine Desynchronisationsschleife zwischen drei Komponenten: der nativen SA:MP-Netzwerk-Engine, der Funktion SetPlayerVirtualWorld und dem Plugin Incognito Streamer. In diesem Artikel untersuchen wir die technischen Hintergründe dieses Bugs und lernen, wie man Spielerkoordinaten und Streaming-Zuweisungen richtig aktualisiert.

Anatomie des Glitches: Warum der Streamer versagt

Die native Server-Engine von SA:MP hat feste Obergrenzen für die Anzahl der physischen Elemente (1.000 Objekte) und Fahrzeuge, die sie gleichzeitig an einen Client senden kann. Um diese Barriere zu umgehen, nutzen alle modernen Skriptarchitekturen das Incognito Streamer-Plugin. Dieses überwacht permanent die Koordinaten jedes aktiven Nutzers und sendet Objekte nur dann an dessen Client, wenn diese in den festgelegten Streaming-Radius (Stream Distance) fallen.

Desynchronisation und das Auftreten unsichtbarer Entitäten entstehen durch eine Störung der chronologischen Reihenfolge von Netzwerkpaketen bei abrupten Änderungen der Koordinaten oder der virtuellen Welt. Ein typischer Ablauf dieses Bugs sieht wie folgt aus:

  1. Das Skript löst eine Teleportation in ein Interieur aus (ändert die Koordinaten via SetPlayerPos und die virtuelle Welt via SetPlayerVirtualWorld).
  2. Der Server sendet sofort einen Befehl за Incognito Streamer: "Spieler hat seine Position geändert; aktualisiere seine gestreamten Objekte!".
  3. Der Streamer leert die alten Caches des Clients und beginnt sofort mit der Berechnung der neuen Objekte für die Zielzone.
  4. Synchronisationsfehler: Der Client des Spielers (der lokale PC) hat aufgrund von Netzwerklatenz (Ping) oder Render-Verzögerungen das primäre Paket zur Positionsänderung vom Hosting-Server noch nicht verarbeitet. Für den lokalen PC befindet sich der Spieler noch im freien Fall oder am alten Spawnpunkt.
  5. Die Objekte des neuen Interieurs werden vom Streamer an den Zielkoordinaten bereitgestellt, an denen der Client laut lokalem PC noch gar nicht angekommen ist. Der lokale Spiel-Client stuft diese Pakete als außerhalb der Reichweite ein und verwirft sie. Der Spieler fällt durch die unsichtbare Geometrie.

Wie man es NICHT machen sollte (Veraltetes, fehleranfälliges Skripting)

Die meisten Entwickler nutzen eine sofortige Spielerverschiebung, die unweigerlich zu Paketverzögerungen führt:

public OnPlayerPickUpDynamicPickup(playerid, pickupid)
{
    if(pickupid == pickup_enter_ls_news)
    {
        SetPlayerVirtualWorld(playerid, 15);
        SetPlayerInterior(playerid, 3);
        SetPlayerPos(playerid, 823.12, -1324.44, 15.40);
    }
    return 1;
}

Der richtige Algorithmus: Temporäre Sperre und erzwungene Stream-Aktualisierungen

Um Desynchronisationen beim Laden zu verhindern, muss eine sichere Teleportation eine feste vierstufige Sequenz einhalten: Einfrieren des Spielers, Aktualisierung der Parameter, erzwungene Stream-Rekompilierung via Streamer_UpdateEx und Aufhebung das Einfrierens nach einer kurzen Latenzpause.

Implementierung einer sicheren Teleportations-Funktion:

stock TeleportPlayerSecure(playerid, Float:x, Float:y, Float:z, interior, virtual_world)
{
    TogglePlayerControllable(playerid, false);

    SetPlayerInterior(playerid, interior);
    SetPlayerVirtualWorld(playerid, virtual_world);
    SetPlayerPos(playerid, x, y, z);

    Streamer_UpdateEx(playerid, x, y, z, virtual_world, interior, streamer_type:STREAMER_TYPE_OBJECT);

    SetTimerEx("UnfreezeTeleportedPlayer", 400, false, "d", playerid);
    return 1;
}

forward UnfreezeTeleportedPlayer(playerid);
public UnfreezeTeleportedPlayer(playerid)
{
    if(!IsPlayerConnected(playerid)) return 1;
    TogglePlayerControllable(playerid, true);
    return 1;
}

Erweiterte Streamer-Konfigurationen

Der Incognito Streamer basiert auf Konfigurationen, die in der streamer.cfg oder direkt via Code in OnGameModeInit festgelegt werden. Die Standardwerte sind für kleine Server optimiert, was bei Großprojekten zu späten Ladezeiten führt.

Für ein sofortiges Laden von Texturen fügen Sie diese Parameter in Ihre OnGameModeInit-Sequenz ein:

  • Streamer_TickRate(20); — Regelt die Zyklusfrequenz des Streamers in Millisekunden (Standard ist 50ms). Das Senken auf 20ms erhöht die Berechnungszyklen, was Verzögerungen beim Laden vor schnellen Fahrzeugen verhindert.
  • Streamer_SetVisibleItems(STREAMER_TYPE_OBJECT, 700); — Definiert die maximale Anzahl an Objekten, die einem Client gleichzeitig angezeigt werden. Setzen Sie dieses Limit nicht höher als 900, um das native SA:MP-Limit (1.000) nicht zu überschreiten, da dies zu Fehlern führt.

Fahrzeug- und Spieler-Streaming-Anomalien (Unsichtbare Zustände im PVP)

Warum werden manchmal echte Spieler-Charaktere oder Fahrzeuge während des Matches unsichtbar? Dies wird durch den nativen Streaming-Radius von SA:MP gesteuert, der im Client fest auf etwa 150-200 Meter programmiert ist.

Wenn Ihre Skripte die virtuelle Welt eines Spielers zu häufig ändern или dynamische Zonen gleichzeitig mit 3D-Texten oder Map-Icons manipulieren, kann die native Engine die Verfolgung verlieren, wodurch Entitäten in unterschiedlichen Welten landen, selbst wenn die Welt-ID übereinstimmt.

Desynchronisationstyp Ursache des Fehlers Lösungsstrategie
Fallen durch Interieur-Texturen Objekte wurden in der neuen virtuellen Welt vor der Schwerkraftberechnung nicht rechtzeitig erstellt Verwendung der Kombination aus Streamer_UpdateEx + kurzem Einfrieren (Freeze)
Unsichtbare Fahrzeuge / Boote Fahrzeuge wurden in Welt 0 erstellt und Interieurs zugewiesen, ohne die Tracking-Buffer zu erneuern Erzwingen Sie eine strikte Interieur-Bindung mithilfe nativer LinkVehicleToInterior-Aufrufe
Unsichtbare Spieler bei Gangfights Netzwerküberlastung (Packet Loss) durch ununterbrochene Aufrufe von Animationsprüfungen Begrenzen Sie Koordinaten-Schleifen auf feste 1-Sekunden-Ticks statt bei jedem Engine-Schritt mitzulaufen

Zusammenfassung: Um Spieler dauerhaft vor unsichtbaren Entitäten zu schützen, sorgen Sie dafür, dass Ihr Skript dem Client eine kurze Pause (300-400ms) zum Laden der Umgebung gönnt, wann immer ein Wechsel virtueller Welten auf den Hardware-Ebenen des Hostings stattfindet.

Ähnliche Artikel

Schutz von SA:MP-Servern gegen Flood-Angriffe und gefälschte Pakete in Pawn

Ein technischer Leitfaden zur Absicherung von SA:MP-Servern vor Paket-Flooding, Dialog-Spam und unzulässigem Fahrzeug-Spawning mittels Pawn.RakNet und Nex-AC.

Weiterlesen

Bekämpfung von Speicherlecks (Memory Leaks) in AMX-Skripten

Ein technischer Leitfaden zur Erkennung und Behebung von Speicherlecks in SA:MP/CRMP-Server-Skripten. Behandelt MySQL-Cache-Freigabe, Streamer-Entitäten und Heap-Bereinigungen.

Weiterlesen

Daten-Caching im RAM mit Pawn: Optimierung der PlayerInfo-Struktur

Ein technischer Leitfaden zur Erstellung einer performanten RAM-Caching-Architektur mittels PlayerInfo-Arrays in Pawn, um die Festplatten-E/A-Last zu minimieren.

Weiterlesen