Исправление бага с «невидимками» и рассинхронизацией виртуальных миров

Техническое руководство по устранению бага с невидимыми игроками и рассинхронизации виртуальных миров в SA:MP/CRMP с помощью правильного использования инструментов Incognito Streamer.

20.05.2026 Русский

Исправление бага с «невидимками» и рассинхронизацией виртуальных миров

Один из самых старых и раздражающих багов в SA:MP/CRMP — это появление так называемых «невидимок». Игрок заходит в интерьер, на спавн или телепортируется на мероприятие, но не видит других участников, кастомные объекты (стены, двери, мебель) или машины, хотя для администраторов и по логам сервера он находится в правильном месте. Бывает и обратная ситуация: игрока убивает «невидимый» противник, который на самом деле стоит прямо перед ним.

В основе этой проблемы лежит рассинхронизация между тремя компонентами: сетевым движком самого SA:MP, функцией SetPlayerVirtualWorld и плагином Incognito Streamer. В этой статье мы разберем техническую изнанку этого бага и научимся правильно обновлять позиции игроков и зоны стрима.

Анатомия бага: Почему ломается стример?

Стандартный серверный движок SA:MP имеет жесткие лимиты на количество объектов (1000) и транспорта, которые он может одновременно отправить клиенту. Чтобы обойти это ограничение, абсолютно все современные моды используют плагин Incognito Streamer. Он постоянно отслеживает координаты каждого игрока и «подсовывает» его клиенту только те объекты, которые находятся в радиусе его видимости (Stream Distance).

Рассинхронизация и появление «невидимок» происходят из-за нарушения хронологии сетевых пакетов при резкой смене координат или виртуального мира (Virtual World). Типичный сценарий багов выглядит так:

  1. Скрипт вызывает функцию телепортации игрока в интерьер (изменяет координаты через SetPlayerPos и виртуальный мир через SetPlayerVirtualWorld).
  2. Сервер моментально отправляет плагину Incognito Streamer сигнал: «Игрок сменил мир и позицию, обнови для него объекты!».
  3. Стример начинает судорожно выгружать старые объекты из памяти клиента и забывает загружать новые.
  4. Сбой синхронизации: Клиент игрока (сам ПК) из-за сетевой задержки (пинга) или долгого прогрузки текстур еще не успел обработать пакет о смене координат от сервера. Для клиента он все еще летит где-то в воздухе или находится на старом спавне.
  5. Объекты нового интерьера создаются стримером там, куда игрок еще «не долетел» по мнению его компьютера. Клиент считает эти объекты слишком далекими и просто их игнорирует. Игрок падает сквозь невидимые текстуры.

Как делать НЕЛЬЗЯ (Классический багованный код)

Большинство разработчиков используют моментальный перенос, который и рождает рассинхрон:

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;
}

Правильный алгоритм: Замораживание и форсирование стрима

Чтобы гарантированно избежать багов прогрузки, профессиональная архитектура телепортации должна состоять из четырех этапов: заморозка игрока, плавная смена данных, принудительное обновление стримера (Force Update) и разморозка после сетевого отклика.

Реализация безопасной функции телепортации (Внедряем в свой мод):

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;
}

Дополнительная оптимизация параметров Стримера

Сам плагин Incognito Streamer имеет файл конфигурации streamer.cfg (или настраивается через Pawn-скрипт в OnGameModeInit). По умолчанию его параметры рассчитаны на слабые сервера, что вызывает задержки прогрузки на крупных проектах.

Для моментальной прогрузки текстур и игроков добавьте в OnGameModeInit следующие настройки:

  • Streamer_TickRate(20); — скорость работы стримера (в миллисекундах). По умолчанию установлено 50мс. Снижение до 20мс заставит стример проверять координаты игроков чаще, что уберет задержки появления объектов перед летящим автомобилем.
  • Streamer_SetVisibleItems(STREAMER_TYPE_OBJECT, 700); — сколько объектов стример может одновременно показать игроку. Не выставляйте больше 900, иначе лимит самого SA:MP (1000) будет превышен, и игра начнет крашиться.

Рассинхронизация транспорта и игроков («Невидимки» в ПВП)

Если с объектами все понятно, то почему становятся невидимыми сами игроки или машины? За это отвечает внутренний радиус стриминга SA:MP (он жестко зашит в клиент и равен примерно 150-200 метрам).

Если вы меняете виртуальный мир игрока слишком часто или используете динамические зоны (например, для зон каптов или интерьеров домов), движок SA:MP может посчитать, что игроки находятся в разных подмирах, даже если ID мира совпадает. Это происходит, если вы вызываете SetPlayerVirtualWorld в один и тот же тик с созданием кастомного 3D-текста или иконки.

Тип рассинхронизации Причина возникновения Способ лечения
Провал под текстуры интерьера Объекты не успели создаться в новом виртуальном мире к моменту падения игрока Использование связки Streamer_UpdateEx + кратковременная заморозка (Freeze)
Невидимые кары / лодки Транспорт был создан в мире 0, а затем перенесен в мир игрока без обновления стрима машин Используйте на сервере LinkVehicleToInterior для принудительной привязки авто к интерьерам.
Невидимые игроки на каптах Перегрузка сетевого канала пакетами (Packet Loss) из-за флуда функциями анимаций Ограничьте частоту вызова циклов, проверяющих координаты игроков (не чаще 1 раза в секунду вместо каждого тика).

Резюме: Чтобы навсегда избавить игроков от «невидимок», приучите свой игровой мод давать клиенту небольшую фору (паузу в 300-400мс) на загрузку окружения при каждом масштабном перемещении по виртуальным мирам хостинга.

Похожие статьи

Защита сервера SA:MP от Flood-атак и ложных пакетов на уровне Pawn

Техническое руководство по настройке защиты серверов SA:MP от сетевого флуда, взлома диалогов и нелегального спавна объектов с помощью Pawn.RakNet и Nex-AC.

Читать далее

Борьба с утечками памяти (Memory Leaks) в AMX-скриптах

Техническое руководство по поиску и устранению утечек памяти в серверных скриптах SA:MP/CRMP AMX, фокусирующееся на очистке кэша MySQL, объектах Стримера и стеке.

Читать далее

Организация правильного кэширования данных (PlayerInfo) в RAM

Техническое руководство по созданию высокопроизводительной архитектуры кэширования в оперативной памяти с помощью массива PlayerInfo в Pawn для снижения дисковой нагрузки I/O.

Читать далее