Open MrTGN opened 7 years ago
Судя по-всему я правильно предположил причину того, почему убрали HitPoint в нативный код. Вот что из себя представляет функция IsHeadShot уже после моей оптимизации:
// Overridden so that anims don't get interrupted on the server if one is already playing
function bool IsHeadShot(vector Loc, vector Ray, float AdditionalScale)
{
local float RayDotLoc, RayDotRay;
if ( bDecapitated || HeadBone == '' )
Return False;
if ( Level.NetMode == NM_DedicatedServer )
CheckDedicatedServerAnim();
UpdateHeadLocation();
if ( bUseOnlineHeadShotCheck )
AdditionalScale = Square(HeadRadius * HeadScale * AdditionalScale * OnlineHeadshotScale);
else
AdditionalScale = Square(HeadRadius * HeadScale * AdditionalScale);
// Express snipe trace line
Ray *= 2.0 * CollisionHeight + 2.0 * CollisionRadius;
// Find Point-Line Squared Distance
Loc = HeadLocation - Loc;
RayDotLoc = Ray dot Loc;
if ( RayDotLoc > 0.0 ) {
RayDotRay = Ray dot Ray;
if ( RayDotLoc < RayDotRay )
Loc = Loc - Ray * RayDotLoc / RayDotRay;
else
Loc -= Ray;
}
Return (Loc dot Loc) < AdditionalScale;
}
В функции IsHeadShot я убрал использование лишних переменных, без которых можно обойтись, вынес проверку анимации и обновление положение головы в отдельные функции с задержкой на обновление, ибо эти параметры не меняются так часто. А так же заменил извлечение квадратного корня на возведение в квадрат, ибо эта операции значительно быстрее. В целом видно, что расчетов все равно довольно много, даже с учетом моей оптимизации.
По той же причине у них PointRadius - это радиус в квадрате.
В общем, все это я к тому, что даже в нативном коде в HitPoint системе все равно довольно много вычислений. И большая нагрузка на сервер. Не зря ведь они это убрали в нативный код. А теперь представим что на сервере одновременно в тела 3-5 монстров влетает сразу 20-30 снарядов из дробовиков. Представляете сколько расчетов одновременно серверу придется произвести? Так что получается, что идея с HitPoint конечно хороша, но тоже далеко не идеальна из-за большой нагрузки расчетами.
Получается, что мне нужно переработать BallisticCollision таким образом, что бы он не блокировал снаряды, а блокировал Trace. И при попадании снаряда в монстра производить TraceActors на расстояние его коллизии. Это позволит мне быстро получать список того, чему наносить урон и сколько энергии снаряд потратит. При этом, на это будет тратится значительно меньше ресурсов. Ведь цилиндры BallisticCollision прикреплены к костям и обновляются движком автоматически. Т.е. не нужно искать и рассчитывать их положение, а так же рассчитывать пересечения. Конечно это BallisticCollision - это спавн лишних объектов на монстре, зато избавление от расчетов. Думаю, это вполне стоит этого. Лучше один раз заспавнить несколько (пусть даже 6) цилиндров BallisticCollision и просто производить Trace через них, чем постоянно, пусть даже и нативно, рассчитывать все это.
Так. Закончил переработку логики BallisticCollision и провел хорошую оптимизацию логики базовых классов снарядов. Теперь все это нужно тестировать, ибо изменение кардинальные. Так же, надеюсь, оптимизация снарядов хорошо скажется на производительности, ибо я постарался максимально убрать лишнее использование переменных и лишние вызовы.
Update: смотреть "выводы" в 3м комментарии. Разработчики Red Orchestra Ostfront 41-45 (RO далее) в свое время написали хорошую систему нанесения урона по частям тела человека. Она довольно простая, но эффективная. Из себя она представляет список цилиндров заданных размеров, прикрепленных к костям или сокетам монстра. Обнаружение попадания по тем или иным HitPoint производится через функцию HitPointTrace, которая возвращает массив с HitPoint, которые были задеты при трассировке.
В настройках HitPoint следующие параметры:
Из комментариев к переменным все вполне понятно. Но там есть неточности. Описание, видимо, копировалось из кода функции IsHeadShot. PointRadius - это радиус в квадрате зоны этого HitPoint. PointHeight - это расстояние от центра до края HitPoint, т.е. пол высоты цилиндра.
Подозреваю что и сама HitPoint система работает по тому же принципу что и логика функции IsHeadShot, с той лишь разницей, что она перебирает все возможные зоны на пути трейса и проверяет пересечет ли она их. Т.е. как таковых HitPoint "цилиндров" на модели нет. Просто идет перебор всех HitPoint от положения их кости и проверяется пересечение с траекторией трейса.
С одной стороны плюс этой системы в том, что она не спавнит никаких лишних объектов на Pawn, зато минус в том, что производит много расчетов. Видимо из-за этого они и убрали эти расчеты в нативный код на C++ и я не могу посмотреть что конкретно там считается.