▪️ 1. Забудь про «Клиент-Сервер» — тут всё — ВЕКТОРЫ
В бэке ты работаешь с сущностями в БД. В геймдеве сущность — это трансформ. Матрица 4x4.
Ты привык:
if (user.age > 18). Теперь ты будешь писать: if (Dot(A, B) > 0.0f). И если ты не поймешь, что такое скалярное произведение — твой персонаж будет летать сквозь стены. Ты управляешь не объектами, а ИЗМЕНЕНИЯМИ В ПРОСТРАНСТВЕ.▪️ 2. Твой первый шок — Кватернионы
В web время идет линейно. В играх — время дискретно (DeltaTime). Если ты используешь Эйлеровы углы (X, Y, Z) для вращения камеры — ты умрешь от Gimbal Lock. Это когда одна ось поворота вырождается, и камера начинает бешено дергаться. Запомни магические числа:
w, x, y, z. Кватернион — это не 4D-вектор, это Ось + Угол.Ты должен поворачивать объект (код на C++/Unreal или C#/Unity):
// ПРАВИЛЬНО: Плавный поворот к цели
Quaternion currentRotation = transform.rotation;
Quaternion targetRotation = Quaternion.LookRotation(target.position - transform.position);
// Самое важное! Slerp (Spherical Linear Interpolation)
// Это не Lerp! Lerp порезает траекторию по хорде, а Slerp — по дуге.
transform.rotation = Quaternion.Slerp(currentRotation, targetRotation, Time.deltaTime * speed);
▪️ 3. Матрицы — твой новый Бог
Ты не двигаешь объект прибавлением к
x. Ты перемножаешь матрицы:MVP = Projection * View * Model➖ Model — где объект лежит в мире.
➖ View — где стоит камера (по сути, обратная матрица позиции камеры).
➖ Projection — перспектива (искажение для эффекта глубины).
Пример: У тебя есть координаты мыши на экране (x=640, y=480). Как найти луч в 3D?
// НЕ пытайся сделать это в лоб. Используй обратную матрицу проекции!
Vector3 screenPos = new Vector3(Input.mousePosition.x, Input.mousePosition.y, 0.5f); // 0.5 - середина глубины
Vector4 worldPos = camera.projectionMatrix.inverse * camera.worldToCameraMatrix.inverse * screenPos;
Перепутаешь порядок умножения (MV вместо VM) — твой луч улетит не туда, куда смотрит камера, а в зеркальное отражение.
▪️4. Аналитическая геометрия — это алгебра, а не геометрия
Здесь всё через SDF (Sign Distance Functions), если ты шейдерист, или через Оси.
Важнейший лайфхак: Вместо вычисления расстояния через корень (
sqrt(dx*dx + dy*dy)) — сравнивай квадраты.sqrt() — это адски дорого для 1000 юнитов.// ПЛОХО:
float dist = sqrt(pow(x1-x2, 2) + pow(y1-y2, 2));
if (dist < 10) { Attack(); }
// ХОРОШО (экономит тебе 0.5 мс фрейма):
float distSq = (x1-x2)*(x1-x2) + (y1-y2)*(y1-y2);
if (distSq < 100.0f) { Attack(); } // 10^2 = 100
▪️5. Как проверить, что игрок в поле зрения?
Это классика для любого стелс-экшена. Тебе нужен Скалярный продукт (Dot Product).
Dot = |A| * |B| * cos(angle)Если нормализовать векторы (длина = 1), то
cos(angle) между взглядом врага и направлением на игрока дает нам ответ:Если
Dot > 0.7 — игрок прямо перед носом (угол 45°).Если
Dot < 0 — игрок за спиной.Код детекции:
Vector3 enemyForward = enemy.transform.forward; // Куда смотрит враг
Vector3 toPlayer = (player.transform.position - enemy.transform.position).normalized;
float dotProduct = Vector3.Dot(enemyForward, toPlayer);
// Угол обзора 90 градусов (Cos(90)=0)
if (dotProduct > 0.0f)
{
// Вижу тебя! (если нет стены, проверяем Raycast)
if (!Physics.Linecast(enemy.position, player.position))
{
enemy.Shoot();
}
}
▫️ Визуализируй. Не верь расчетам в уме. Нарисуй
Debug.DrawLine() и DrawRay() для каждого вектора. Если ты не видишь линии в редакторе — ты гадаешь.▫️ Системы координат. Всегда знай, в каком пространстве ты сидишь: World Space, Local Space или Screen Space. Перепутал — объект улетел.
▫️ Сначала геометрия, потом физика. Физика пинает объект через силу. Геометрия просто говорит "я здесь". Хочешь просто поставить объект на полку — используй
MovePosition, а не AddForce.Программист тратит 3 дня на дебаг, почему персонаж улетает в космос. Геймдев-программист знает, что это Gimbal Lock или переполнение
float после умножения матриц.База: "3D Math Primer for Graphics and Game Development".
💡 Physics.Math.Code // @physics_lib
