Математика в Gamedev по-простому
Kanalga Telegram’da o‘tish
Как на самом деле работают стрельба, толпа NPC, графика, физика тканей. Канал про то, что ИИ не заменит: понимание. Разборы на пальцах, рабочий код, интерактивы. dev-math.ru Сотрудничество: @it_bizdev
Ko'proq ko'rsatish442
Obunachilar
Ma'lumot yo'q24 soatlar
+177 kunlar
+9130 kunlar
Postlar arxiv
Одного числа мало. Рейтингу нужна погрешность
В среду мы оставили ELO с фиксированным K — фильтром, который не знает, когда сам себе не доверяет. Новичок и ветеран с рейтингом 1500 для него одинаковы, хотя первое — это «без понятия», а второе — «проверено сотней матчей».
Лечится одним движением: добавьте к рейтингу второе число — насколько система в нём уверена. Это и есть Glicko (Марк Гликман, 1995): рядом с рейтингом живёт RD, разброс оценки. И вот тут сигнал/шум возвращается красиво — RD это, по сути, адаптивный K. Большой RD (новичок или вернулись после года) → рейтинг идёт крупными шагами, жадно ловит сигнал; маленький (тысяча партий за плечами) → шаги мелкие, шум давится. K больше не подбирают руками, он вытекает из уверенности. И сам RD падает, когда вы играете, и растёт за время простоя — старые данные протухают.
TrueSkill (Microsoft Research, 2006, под Halo на Xbox Live) доводит идею до предела: скилл — не точка, а нормальное распределение N(μ, σ), где σ — та же неуверенность, что RD. Матч смещает и сужает колокол. И — чего ELO не умел в принципе — перформанс команды складывается из распределений игроков, так что через factor graph система раздаёт +/− по всей пятёрке после одного матча 5v5.
Ни RD, ни σ не спасают от всего. Они не знают, что вы тильтуете, не отличают соло от стака с друзьями и не ловят смурфов — тот же опытный игрок на новом аккаунте в CS для них просто «новичок с большим σ», которого математика догонит за десяток матчей, испорченных всем остальным. Это уже поведенческие системы, не рейтинг.
В статье — полный разбор: апдейт TrueSkill через factor graph на одном примере, Glicko-2 с псевдокодом и интерактив, где вы сами крутите рейтинги и σ и смотрите, кого алгоритм считает честной парой.
🔥 — если дочитали до factor graph.
#мат_геймдев #МатРазбор #матчмейкинг #алгоритмы
Рейтинг — это не скилл, а оценка скилла
Ваш истинный скилл — это число, которого никто никогда не видел. Ни вы, ни сервер. Измерить напрямую нельзя — только догадываться по результатам матчей.
А один матч — это плохие данные. Выиграли, потому что сильнее? Или соперник тильтанул, лагнул, один раз зевнул в CS? В одной игре сигнал (ваш скилл) намертво смешан с шумом (везение). Это всего один бит информации о вещественном числе — всерьёз оценивать по нему нечего.
И тут немного надо понимать логику сигнал-шум. Вы сыграли 1000 матчей. У вас есть ваш скилл (сигнал), а есть удача (шум) в любой игре. Тут уже сигнал будет виден ярче, так как всегда чем больше выборка, тем меньше влияние шума на сигнал. Но кроме этого шум мы умеем матиматически фильтровать, в попытках найти истинное значение сигнала.
Собственно, поэтому ELO не «считает» скилл, а фильтрует его из шума:
E_a = 1 / (1 + 10 ** ((R_b - R_a) / 400)) # модель предсказывает исход
R_a = R_a + K * (S_a - E_a) # факт минус прогноз → поправка
Первая строка — прогноз модели. Вторая — поправка: та же механика, что у экспоненциального сглаживания, новая оценка = старая плюс доля ошибки прогноза S_a − E_a. K — размер этой доли, по сути learning rate: насколько доверять одному матчу.
И тут весь фокус фильтра. Большой K хватается за каждый результат: два равных игрока, каждый матч — монетка, но при K=40 рейтинг скачет на ±20 за партию, хотя скилл не двигался. Это шум, просочившийся в число. Маленький K усредняет много игр — гладко, но реальный рост догоняет медленно. Поэтому FIDE душит шум топам, опуская K до 10: у Карлсена скилл давно известен, дёргать рейтинг из-за одного зевка незачем.
Загвоздка в том, что K фиксированный. Умный фильтр сам бы понимал, когда он не уверен — и доверял данным, а когда уверен — глушил шум. А вот об этом мы и поговорим в статье.
🔥 — если поняли «скилл = сигнал, отфильтрованный из шума». Ну и не забываем делиться с друзьями, это помогает развитию канала.
#мат_геймдев #МатРазбор #матчмейкинг #алгоритмыСкрытое число
В голосовании за тему на втором месте шло ELO и MMR, так что это неделя будет про них. Прямо сейчас у вас есть рейтинг. Даже если вы его ни разу не видели и не сыграли ни одной ранкед-игры — система всё равно держит про вас число.
Заходите вечером в CS или Dota, жмёте «Найти игру» — и через минуту перед вами девять других людей. Откуда сервер знает, что подходят именно эти девять?
Под капотом — математика, которую придумали для шахмат в 1960-х. Та самая, по которой считают рейтинг Магнусу Карлсену: FIDE приняла её в 1970-м, отсюда слово ELO. А дальше она расползлась по всему соревновательному геймдеву — Halo, Rocket League, Lichess, LoL. Движки рейтинга у всех разные, идея одна: у игрока есть скрытое число (MMR), алгоритм сводит близких и пересчитывает всех после матча.
И вот тут начинается интересное. Шахматист играет 1v1 годами. А матчмейкер в шутере должен за секунды собрать из миллионов человек онлайн партию 5v5 с исходом близким к 50/50 — да ещё с поправкой на регион, пинг и штрафы за поведение. По сути это уже не сортировка по рейтингу, а вероятностная модель.
На неделе разберём её целиком: формула ELO в три строчки, почему её перестало хватать, и как Glicko с TrueSkill раздают рейтинг команде из пяти человек после одного матча.
🔥 — если хочется узнать, откуда берётся ваш MMR или написать свою систему рейтинга игроков.
#мат_геймдев #МатРазбор #матчмейкинг #геймдизайн
Толпа на максималках: flow fields, GPU и десятки тысяч юнитов в кадре
https://dev-math.ru/articles/crowd-gpu/
Помните прошлую статью про толпу? Я остановился на тысяче юнитов и оставил четыре вещи «на потом» — flow fields, симуляцию на GPU, indirect draw и LOD AI. Обещал продолжение, да и вы за него проголосовали — и вот оно 🙂 Четыре интерактива (один — честная 3D-сцена на three.js, с реальным счётчиком draw call'ов), и снова получилось так объёмно, что впору сшивать в книжку. Жду огоньков и репостов друзьям 🔥
Тысяча юнитов на CPU — это разминка. Десятки тысяч в кадре (Париж в AC Unity, битвы Total War, орды нежити) — уже другая архитектура из четырёх слоёв. Глобальный путь перестаёт быть тысячей независимых A* и становится одним flow field — сеткой направлений на всю толпу за O(1). Симуляция агентов уезжает с ядер CPU на тысячи дорожек GPU (compute shaders + StructuredBuffer). Рендер перестаёт быть draw call'ом на агента и становится indirect draw, где команды отрисовки генерит сам GPU. А то, что не видно вблизи, не считается честно — LOD AI и recycling. В финале — разбор под капотом Planetary Annihilation, Supreme Commander 2, AC Unity, Total War, They Are Billions и Helldivers 2.
Первая часть, если пропустили: https://dev-math.ru/articles/crowd/
#мат_геймдев #МатРазбор #algorithms #GPU
Flow fields: один расчёт вместо тысячи A*
Тысяча юнитов идёт к одной точке. Если для каждого считать A* — тысяча независимых поисков за кадр. Дороговато.
Как нам сделать меньше расчётов? По своей сути, идея проста: можно сделать один расчёт вместо тысячи. Посчитали поле — все юниты просто читают из него «куда идти из своей клетки».
Разбиваем карту на сетку. От цели обратной волной (Dijkstra) в каждой клетке считаем дистанцию до цели и записываем вектор на соседа — это и есть flow field. Юниту достаточно прочитать вектор из своей клетки. O(1) на запрос, без зависимости от длины пути и количества юнитов.
«А если цель движется?» В RTS — почти никогда. Клик в точку, поход к зданию — цель статична, поле живёт минутами. При движущейся цели перерсчитать получается в любом случае не так дорого. Одну дейкстру пустить по карте не так долго, как для каждого юнита считать А*. Тем более с шумом от boids там не обязательно моментальная реакция на пользовательский ввод или триггеры.
Проблема возникает если много юнитов и у каждого своя цель — A* снова в выигрыше. Flow fields — это про движение толпы к общей цели. Канонический разбор — Elijah Emerson, AI Game Programming Wisdom 5 (2008).
#мат_геймдев #МатРазбор #algorithms #AI
Тысяча юнитов в кадре — это, конечно, эффектно. Но в AAA это только начало.
Давайте пройдемся до конца по толпе тогда (по результатам опроса). А потом уже пойдем либо к лутбоксам, либо к ELO и MMR.
В прошлой статье мы разобрали, как оживляют тысячу юнитов через boids + spatial hash на CPU. При этом в Assassin's Creed Unity на улицах Парижа — до 10 000 NPC одновременно. В массовых битвах Total War: Warhammer 2 — тоже десять тысяч, у каждого свой коллайдер и анимация. В Helldivers 2 — плотные волны термидов на одного игрока. They Are Billions — название говорит за себя.
По сути, любая CPU-архитектура решения из прошлой статьи на этом масштабе отвалится. У проблемы два слоя, которые мы не разобрали — глобальная навигация через flow fields (много готовых реализаций, но для такой задачи уже лучше написать свою) и перенос симуляции на GPU (compute shaders + indirect rendering).
Разберем на этой неделе. Всё как обычно со статьей в конце недели. Данная тема прикольна ещё тем, что если углублятся в детали реализации (особенно рендера), то станет понятнее как работает та же Nvidia Flex и подобные технологии.
Ну и делимся постами, ставим реакции, пишем чего хотелось бы ещё в комменты. Короче статьи, больше каких-то примеров. Хочется понимать, что интересно, а что нет. А то по SDF статью посмотрело меньше народу, чем даже по толпе, а вышла она на неделю раньше.
#мат_геймдев #МатРазбор #algorithms #performance
Мне нравится предлагать темы на выбор. Что разбираем дальше? Свою тему, как и в прошлый раз, можно предложить в комментариях. Она может пойти в опрос следующей недели. Что же победит на этой?
Толпа без AI: как три правила, хеш-сетка и ORCA делают массовку живой
https://dev-math.ru/articles/crowd/
Вы просили про толпу. Ну держитесь 🙂 Семь разделов, шесть интерактивов и тысяча юнитов в одном экране браузера. Я заморочился — получилось так объёмно, что статьи скоро можно сшивать в книжку. Жду огоньков и репостов друзьям 🔥
Симуляция массовки упирается в две проблемы: общий behavior tree «толпа делает X» не масштабируется, а наивный поиск соседей даёт O(N²) и кладёт сцену уже на пятистах юнитах. В статье разбираю архитектуру по слоям: три правила Рейнольдса для группового движения, uniform spatial hash для поиска соседей за O(N), упрощённый ORCA для встречных потоков в коридоре, steering behaviors для целей и обхода препятствий, плюс отдельная часть про GPU instancing для рендера тысячи юнитов одним draw call'ом. В финале — разбор под капотом AC Unity, World War Z, They Are Billions, Vermintide 2 и RTS-обобщённо.
#мат_геймдев #МатРазбор #algorithms #AI
Толпа на сетке: 9 клеток, а не миллион проверок
В boids каждому юниту нужны его ближайшие соседи — без них не сработают ни separation, ни alignment, ни cohesion. Наивный ответ — пройтись по всем и проверить расстояние:
// плохо: O(N²) на каждом кадре
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if (i == j) continue;
if ((boid[i].position - boid[j].position).sqrMagnitude < r * r) {
// учесть соседа
}
}
}
Считаем по головам. 100 юнитов — 10 000 проверок за кадр. 500 — 250 000. 1000 — миллион. И всё это 60 раз в секунду.
Итак, spatial hash. Соседи по определению рядом — значит, проверять надо только тех, кто в той же зоне пространства. Разбиваем сцену на клетки фиксированного размера, раскладываем юнитов по клеткам и смотрим рядом:
// каждый кадр пересобираем
var grid = new Dictionary<Vector2Int, List<Boid>>();
foreach (var b in boids) {
var cell = new Vector2Int(
(int)(b.position.x / cellSize),
(int)(b.position.z / cellSize));
if (!grid.TryGetValue(cell, out var list))
grid[cell] = list = new List<Boid>();
list.Add(b);
}
Размер клетки чаще всего берут равными радиусу видимости соседей.
По сути алгоритм boids — это часть задачи. Ещё часть — найти соседей достаточно быстро. Без этого игры с сотнями юнитов на экране просто не существовали бы. 🔥 Кроме того их надо отрендерить, а об этом уже поговорим позже.
#мат_геймдев #МатРазбор #algorithms #optimization**Boids: три правила стаи*
Когда вы смотрите на стаю скворцов на закате, кажется, что это один организм с общей волей. На самом деле там нет лидера: каждая птица следит примерно за семью ближайшими соседями — независимо от того, как далеко они оказались. Это измерили Ballerini и соавторы в 2008 году по стереосъёмкам стай над Римом (PNAS).
Сам алгоритм старше. Крейг Рейнольдс собрал три правила ещё в 1987-м (SIGGRAPH '87). Само слово boids — от bird-oid object:
— separation — отталкивайся от того, кто оказался слишком близко.
— alignment — подстраивай свою скорость под среднюю скорость соседей.
— cohesion — тянись к их центру масс.
Собственно, в Unity это делается так:
Vector3 sep = Vector3.zero, ali = Vector3.zero, coh = Vector3.zero;
int count = neighbors.Count;
foreach (var other in neighbors) {
Vector3 d = transform.position - other.position;
if (d.sqrMagnitude < sepRadius * sepRadius) sep += d.normalized;
ali += other.velocity;
coh += other.position;
}
velocity += wSep * sep
+ wAli * (ali / count - velocity)
+ wCoh * (coh / count - transform.position);
velocity = Vector3.ClampMagnitude(velocity, maxSpeed);
transform.position += velocity * Time.deltaTime;
Магия — в балансе весов. Большой wSep — юниты разлетаются в пыль. Большой wCoh — слипаются в шарик и стоят. Всё интересное — где-то между.
В играх это стаи в Subnautica, орда Freakers в Days Gone, Swarm Engine в World War Z. Конечно же, в боевой реализации есть ещё seek к цели и avoidance препятствий — но базовая стая держится на этих трёх правилах. 🔥
#мат_геймдев #МатРазбор #AI #biomimicryТолпа без AI: сотни юнитов на трёх правилах
По голосованию победитель очевиден. Так что начнём. У парижан в Assassin's Creed Unity нет интеллекта. У каждого крысака в Vermintide и зомби из World War Z — тоже. Когда в кадре одновременно сотни персонажей, если бы у каждого крутилось полноценное behavior tree, FPS умер бы.
Так что там — не AI, а несколько локальных правил: «не наступай на ноги соседям», «иди примерно туда же, куда соседи», «не отставай». Собственно, это и есть толпа в играх — эмерджентность. Крейг Рейнольдс описал это в 1986 году и назвал boids.
Дальше начинается инженерия. Days Gone крутит орду из сотен Freakers. World War Z — Swarm Engine с зомби, текущими по уровню как жидкость. Под капотом везде одно и то же: boids, spatial hashing, ORCA, плюс LOD AI на дальних юнитах.
На неделе разберём: три формулы Рейнольдса, почему наивная реализация умирает на 500 юнитах, как ORCA не даёт юнитам сталкиваться в узких местах. 🔥
#мат_геймдев #МатРазбор #AI #algorithms
SDF и raymarching по-простому: от smin до мешей и обратно
https://dev-math.ru/articles/sdf/
Как из двух сфер собирается одна капля через smin, как sphere tracing рендерит её без единого треугольника, и почему в реальных играх SDF чаще локальный VFX, чем основной рендер. Шесть разделов, шесть интерактивов в браузере, плюс ответы на два вопроса: «А цена sdf(p) какая?» и «А что с мешами в SDF?».
Завершим цикл того о чём я писал на неделе статьёй с ответами на вопросы в комментах, и я пошел думать что буду рассказывать на следующей неделе. 🔥 как всегда приветствуются. Это классическая валюта собираемая мной за классные статьи. Работаю за "классы" :)
#мат_геймдев #МатРазбор #шейдеры #VFX
Raymarch на 5 fps — это не GPU виноват. Это вы шагаете неправильно
У вас есть SDF и луч. Как найти, где луч упирается в поверхность? Самый очевидный ответ — идём вдоль луча маленькими шагами и проверяем, попали ли.
// плохо: фиксированный шаг
for (int i = 0; i < 1000; i++) {
if (sdf(p) < EPS) return p;
p += dir * 0.01;
}
И вот ловушка. Шаг маленький — тысячи итераций на пиксель, шейдер выдает 5 fps. Шаг большой — луч проскакивает сквозь тонкие объекты, артефакты по всей сцене. Компромисс «либо медленно, либо неточно». А хочется оба.
Собственно, в чём идея. SDF возвращает расстояние до ближайшей поверхности. Значит, можно шагнуть ровно на это расстояние — и гарантированно не пройти насквозь.
// хорошо: sphere tracing
for (int i = 0; i < 64; i++) {
float d = sdf(p);
if (d < EPS) return p;
p += dir * d; // ← шаг ровно SDF
}
Близко к поверхности шаги мелкие (поле говорит «осторожно, рядом»), в пустоте — большие («лети спокойно»). Обычно 30–60 итераций на всю сцену.
По сути, вся магия SDF держится именно на этой идее. Без sphere tracing формулы расстояний были бы просто красивой математикой без практического смысла.
#мат_геймдев #МатРазбор #шейдерыКак лепят миры из пластилина
В SDF-мире вся геометрия — это функции расстояния. Объединение двух объектов?
min(a, b). Ставите две сферы рядом, берёте min — и получаете не каплю, а два камня, лежащих друг на друге. Жёсткий стык, шов на пиксель.
А хочется ртути. Слизи. Жидкого золота. Капли воды, которая стекает и сливается с другой. Нужно мягкое объединение.
Собственно, вот оно — polynomial smin:
float smin(float a, float b, float k) {
float h = clamp(0.5 + 0.5 * (b - a) / k, 0.0, 1.0);
return mix(b, a, h) - k * h * (1.0 - h);
}
k — ширина шва. k=0 — жёсткое объединение, обычный min. k=0.3 — между сферами протягивается перешеек. k=1 — две сферы превращаются почти в каплю.
Эта формула везде, где в кадре что-то текучее: лава и слизь во многих играх, любая «жидкая» геометрия в шейдерных демосценах. Конечно же, в больших AAA-катсценах жидкость чаще пекут в alembic-кэш — но это уже не процедурка, а проигрывание заранее посчитанной симуляции. У smin своя ниша.
smin выигрывает у alembic-кэшей везде где что-то меняется от ввода игрока в реальном времени. Боссы-слизни, которые делятся и сливаются. Кровь и слизь, динамически стекающиеся в лужи под ногами. Терраморфинг от взрывов, налипание снега. Жгуты энергии из руки игрока к цели. Запечённую симуляцию тут не подсунешь — форма зависит от того, что игрок делает прямо сейчас. А smin честно считает её на лету.
Основная проблема SDF и Raymarching — это производительность. И это главная причина почему SDF не вытеснили полигоны. Но с нынешними мощностями устройств эти техники применимы «локально». Когда полученная ими визуализация композится в сцену. Например, VFX заклинания или какие-то отдельные эффекты.
#мат_геймдев #МатРазбор #шейдерыВ Dreams на PS4 нет ни одного полигона. Совсем.
Взгляните на знаменитый Shadertoy «Happy Jumping» от Inigo Quilez — по экрану прыгает живая капля с глазами, мягкими тенями, AO. Никаких треугольников. Только SDF.
Это signed distance field и raymarching. Геометрия описана математически: для любой точки в пространстве функция возвращает то, как далеко до ближайшей поверхности.
Академическая штука для красивых демок? Конечно же нет. Всё это можно использовать в продакшене. Dreams от Media Molecule целиком построена на SDF — вся игра, все пользовательские ассеты. Doom Eternal считает через SDF-brushes свою gore-систему (есть отдельный Siggraph 2020 talk). Claybook делает на этом пластилиновую физику.
Шейдер персонажа Inigo Quilez выглядит круто, помещается в один небольшой файл, работает в браузере. Но у этого есть своя цена — и именно поэтому в играх raymarching чаще локальный эффект, чем основной рендер.
В статье на этой неделе разберём: что такое distance field, как работает sphere tracing, почему две сферы сливаются в каплю через одну функцию smin и откуда берутся "почти бесплатные" soft shadows. Плюс попробую сделать демки на WebGL чтобы можно было покрутить параметры самостоятельно 🔥
#мат_геймдев #МатРазбор #шейдеры #VFX
О стрельбе в играх по-простому: hitscan, projectile, recoil, lag compensation — шесть пластов под кнопкой выстрела
https://dev-math.ru/articles/shooting/
Шесть параграфов с интерактивами, формулами и кодом на C#. Если когда-нибудь в команде звучало «ну стрельбу-то сделаем за выходные», а потом неделями отлавливали «попал — не засчиталось», статья ровно про это. Жду 🔥 и репостов друзьям-геймдевам 😆
В статье о том, что под одним «нажал курок» лежит шесть независимых задач, и каждая решается по-своему:
▸ Hitscan vs projectile — архитектурный выбор: мгновенный луч (CS, Valorant) или физический снаряд (Quake, Kraber в Apex). За выбором тянется хвост: lag compensation, recoil, ощущаемая отзывчивость.
▸ Хитбоксы — почему индустрия стандартизировалась на капсулах, а не на полигональном меше. Valve в сентябре 2015 целиком переписали систему именно ради этого.
▸ Спред пули — почему два независимых random дают квадрат вместо круга, и как полярные координаты с √ это лечат.
▸ Recoil-паттерны — детерминированная таблица в духе AK-47, которую pro-игроки заучивают как стихи.
▸ Упреждение — банальное квадратное уравнение для AI-снайперов, решаемое за десять строк кода.
▸ Lag compensation — зачем сервер откатывает мир на 80–200 мс назад на каждом выстреле.
По дороге — интерактивы, в которых можно покрутить параметры руками, и сниппеты на C#.
Если соберём 200 🔥 — пишу продолжение по теме, которая больше всего зайдёт в комментариях (баллистика снайперок, penetration через стены, ricochet, damage falloff…).
#мат_геймдев #МатРазбор #шутеры #алгоритмы
Cone-uniform vs Gaussian
Равномерный диск — это честно, но не реалистично. В жизни большинство пуль летит ближе к центру прицела, а не равномерно по всему конусу. Gaussian-распределение это отражает: пули кучкуются вокруг центра, хвосты редкие.
На практике разница такая: в CS-подобных играх первый выстрел — почти точный, разброс нарастает с темпом стрельбы. Это не равномерный диск и не чистый Gaussian — это детерминированный паттерн поверх него. Но базовый случайный спред лежащий в основе чаще всего именно Gaussian.
function gaussianRandom(mean = 0, std = 1): number {
const u = 1 - Math.random();
const v = Math.random();
return mean + std * Math.sqrt(-2 * Math.log(u)) * Math.cos(2 * Math.PI * v);
}
const dx = gaussianRandom(0, spread);
const dy = gaussianRandom(0, spread);
Собственно, выбор между uniform и Gaussian — это выбор ощущения. Uniform читается как «аркада», Gaussian — как «оружие с характером». Когда что уместно — разберём в конце недели, там же детерминированные паттерны и recoil-кривые.
#мат_геймдев #шутеры #алгоритмыКвадратный спред: почему углы «едят» ваши пули
Наивная реализация:
dx = Random(-spread, spread), dy — то же самое. Распределение равномерное, но форма — квадрат. А диагональ квадрата длиннее стороны в √2 раз, так что в угловых направлениях пуля улетает на spread * 1.41 вместо spread. Конус разброса физически не круглый — и это чувствуется.
Правильный вариант — полярные координаты:
const angle = Math.random() * Math.PI * 2;
const radius = spread * Math.sqrt(Math.random());
const dx = Math.cos(angle) * radius;
const dy = Math.sin(angle) * radius;
Почему sqrt? Без него точки кучкуются к центру — площадь кольца растёт с радиусом, а вероятность нет. sqrt это компенсирует и даёт равномерную плотность по всему диску.
В конце недели — полный разбор: cone, gaussian, детерминированные паттерны и когда равномерный диск вообще не нужен.
#мат_геймдев #шутеры #алгоритмыHitscan vs projectile: почему выбор механики стрельбы — это архитектурное решение
Рейлган в Quake попадает в момент нажатия — это raycast, один вызов, результат за кадр. Ракета — честный физический объект со своей скоростью: пока летит, противник уже не там, и целиться нужно в точку, где он окажется через ~400 мс.
Первый подход стал стандартом для тактических шутеров — CS, Valorant. Второй живёт в аркадных — Quake, UT, частично Apex. И это не вкусовщина: за выбором тянется целый хвост — lag compensation на сервере, recoil-паттерны, вся ощущаемая отзывчивость стрельбы.
На следующей неделе давайте разберём, когда какой выбирать и как это реализуется под капотом.
#мат_геймдев #шутеры #алгоритмы
Endi mavjud! Telegram Tadqiqoti 2025 — yilning asosiy insaytlari 
