В рамках моего пути обучения .NET Binary Instrumentation я решил модифицировать игру в Unity под названием Profane, и после всех возможностей подключения, которые я получил, когда решил использовать Harmony, я решил создать несколько хакерских функций. и веселиться.

Одной из вещей, которую я хотел реализовать, был AimBot, который изменял бы вращение камеры, заставляя ее указывать прямо на цель при нажатии определенной клавиши.

Фактическая часть Прицеливания бота была простой, потому что в Unity все, что вам нужно, чтобы заставить камеру указывать в новом направлении, - это изменить свойство Rotation (которое является Quaternion) CameraObject.

Ниже описан процесс того, как заставить камеру указывать на какую-то цель:

1. Измените положение CameraObject, чтобы оно совпадало с положением игрока
2. Получите вектор, представляющий направление от игрока к цели, путем вычитания вектора, представляющего целевую позицию, из вектора, представляющего позицию игрока.
3. Преобразуйте вектор направления в кватернион с помощью функции `UnityEngine.Quaternion.LookRotation`.
4. Установите полученный кватернион в качестве свойства поворота объекта камеры, а затем переместите камеру от игрока. некоторыми юнитами, так как это игра с камерой от третьего лица.

Все это нормально и очень хорошо работает! Единственная проблема, с которой я столкнулся, заключалась в том, что после отпускания горячей клавиши, которая заставляла мою камеру указывать на цель, она внезапно перескакивала в случайное «вращение / направление», и я говорил «черт возьми».

Что ж, все это было очень логичным и имело большой смысл, потому что произошло то, что игра постоянно отслеживала движения мыши и сохраняла их дельты в переменных для осей X и Y, и эти значения передавались в алгоритм чтобы создать реальный опыт вращения камеры от третьего лица с помощью движений мыши, которые мы делали.

Мне нужен был способ сгенерировать новые значения для X и Y, которые при прохождении через алгоритм игры генерировали бы точно такое же положение и поворот камеры, поэтому, когда я отпустил горячую клавишу прицеливания, экран все еще был бы направлен на цель, и не выброшено в случайном направлении.

Вот изображение разборки функции, отвечающей за обновление положения игровой камеры:

Создание обратной функции для части кода, отвечающей за генерацию положения / поворота камеры с учетом X и Y, не было бы очень простой задачей, поэтому я решил вместо этого попробовать новый подход.

Сначала я написал код для отображения некоторой внутренней информации, касающейся состояний переменных cameraXRotation и cameraYRotation, а также свойства Rotation объекта камеры. Перед отображением квартениона я преобразовал его в углы Эйлера, а затем преобразовал градусы в радианы.

Эту «Отладочную информацию» можно увидеть в средней верхней части игрового экрана ниже:

В основном я мог наблюдать, что переменная cameraXRotation была связана со вторым значением кортежа угла Эйлера, а cameraYRotation была связана с первым значением кортежа, поэтому, когда я изменил одно с помощью мыши, другое также изменилось бы пропорционально .

Связь между cameraXRotation и фактическим горизонтальным вращением камеры была очень простой, я заметил, что мне просто нужно было получить радианное представление угла Эйлера и вычесть из него 3,14. С этим значением игра генерирует для меня точно такое же горизонтальное вращение.

Настоящей проблемой было смоделировать связь между осью Y и вертикальным вращением камеры. Поскольку у него было два алгоритма генерации в зависимости от угла, под которым вы смотрели, мне пришлось смоделировать две функции.
(Отсюда этот первый оператор if в коде, показанном ранее.)

Вначале я решил вручную записывать отношения между этими двумя парами и нанес эти данные на график, чтобы увидеть, что отношения между ними, как и следовало ожидать, не являются линейными:

Так что мне нужно было найти способ смоделировать это поведение математически, и пока я пытался найти ответ, я также играл в Desmos с нанесенными на график данными, пытаясь найти какой-нибудь полином, который подходил бы к кривой.

И по счастливой случайности мне удалось найти очень простой полином, который подходил к одной из кривых с полной точностью, это была кривая, представляющая соотношение между вертикальным вращением и координатой Y мыши, когда игрок смотрел ниже линии горизонта.

Еще был случай, когда игрок смотрел над линией горизонта, что я не мог точно смоделировать, возясь с Desmos:

Итак, я просто понял, что могу просто ввести код в игру, чтобы выгрузить много данных, и они используют полиномиальную регрессию, чтобы найти математическую модель, основанную на полиномах, которая идеально вписывалась бы в кривую. И вот что я сделал!

Имея 82 КБ данных, у меня было достаточно точек, чтобы построить красивую кривую, представляющую отношения между теми значениями, которые действительно имели место в игре.

Алгоритм сгенерировал для меня полином третьей степени, который соответствовал моим данным с точностью почти 100%.

Затем я использовал эту модель, чтобы заставить целого робота работать так, как ожидалось, с небольшими усилиями в отношении построения модели, поскольку машинное обучение позаботилось об этом за меня! 😺