Смотри, у тебя реально нормальная архитектура (судя по коду), просто в чате ты объяснил задачу криво, и люди тебя не поняли — начали думать, что ты не понимаешь tick-based. Дам тебе развёрнутое сообщение, которое закрывает вопрос сразу и не даёт свернуть в сторону "а зачем тебе рейкаст вообще".
Вот текст, который можно кинуть в дискорд:
Окей, распишу подробно, чтобы не было путаницы.
Да, у нас tick-based сервер, клиент шлёт команду выстрела с своим Time (client time с учётом interpolation delay). Сервер это время получает и должен откатить мир назад (lag compensation / server-side rewind), чтобы проверить: попал ли выстрел с точки зрения клиента в момент, когда он стрелял.
Проблема НЕ в том, что нет тиков или что я не понимаю tick-based. Проблема конкретно физическая:
У меня на сервере для каждого игрока есть история позиций (Queue<Snapshot> с Time + Pos), пишется с частотой writeRate. Когда приходит выстрел с Time = T:
Мне нужно узнать, где были все остальные игроки в момент T (интерполирую между двумя ближайшими snapshot'ами — GetSnapshot(time)).
Реальные коллайдеры игроков двигать в эту позицию нельзя — это сломает live-физику (столкновения, движение, всё что происходит "сейчас" на сервере).
Поэтому у каждого игрока есть пул из 12 фантомных коллайдеров (CapsuleCollider2D, отдельные GameObject'ы, обычно enabled = false).
На момент запроса рейкаста: беру свободный фантом, ставлю его transform.position в rewind-позицию (snapshot.Pos), включаю (enabled = true).
Делаю Physics2D.SyncTransforms() один раз на весь набор фантомов (не по одному!) — это нужно, чтобы Unity physics engine увидел новые Transform-позиции и рассчитал их bounds/shape в physics world, потому что autoSyncTransforms у меня выключен.
Кидаю Raycast/CircleCast/OverlapCircle по слою PhantomLagCompensation | Ground.
Выключаю все использованные фантомы обратно, возвращаю позицию в 0 (relative to owner), помечаю слот свободным.
Вопрос был не "зачем тик-бейсед" и не "зачем рейкаст" — вопрос был чисто про производительность шага 5: SyncTransforms() — насколько он дорогой, если такое происходит несколько раз за FixedUpdate (условно 10-20 выстрелов/проверок земли в один тик от разных игроков).
Уточнение по поводу "просто синкать Vector3Int" — так и есть, я НЕ синкаю через Mirror/сеть, это чисто локальная серверная операция. SyncTransform тут вообще не про Mirror-синхронизацию клиент-сервер, это Physics2D.SyncTransforms() — API-вызов Unity, который проталкивает Transform в физический движок. Слово "sync" совпало, но это два разных понятия, отсюда и путаница в чате.
Мой вопрос в итоге:
Насколько дорого вызывать Physics2D.SyncTransforms() несколько раз за один FixedUpdate (условно 10-20 раз), если сцена физически лёгкая (только капсулы игроков + простая геометрия карты)?
Стоит ли вместо этого копить все rewind-запросы за тик в очередь и делать один SyncTransforms() в конце FixedUpdate на все сразу (батчинг), вместо синка на каждый отдельный рейкаст?