Sidebar

Скрытие энтитей на расстоянии

Next Day

New member
23.12.2019
26
10
3
Ну в том же самом месте 80fps c новым кодом ,а без него 62fps до этого 29fps
 
  • Love
Reactions: Aynekko

Next Day

New member
23.12.2019
26
10
3
К сожалению после 2 правки был обнаружен баг в мультиплеере.
Если сервер далеко и энтитя у него не отображается то и у клиента ее тоже не будетo_O
Есть мысли как это исправить?Не хотелось бы от этого отказываться!
 

Aynekko

Маппер
Команда форума
Супер Модератор
07.06.2010
3 629
28
  • Золотая медаль RC
  • Бронзовая медаль 216
Если сервер далеко и энтитя у него не отображается то и у клиента ее тоже не будет
Ага, вот и баг подъехал. Спасибо, что протестировал. Мультиплеером я не занимаюсь и его особенностей не знаю.
Попробуй вот что сделать - вместо INDEXENT( 1 ) написать INDEXENT( player ).
 

Next Day

New member
23.12.2019
26
10
3
Ну я прописал INDEXENT( player ) скомпилировал перестал работать прожектор если ему задать дистанцию ,но это фигня без дистанции работает.
Энтити перестали пропадать у клиента.:)
Самое главное то что фпс теперь такой же как без этого кода:( что получается он не работает или работает неправильно?!
 

Aynekko

Маппер
Команда форума
Супер Модератор
07.06.2010
3 629
28
  • Золотая медаль RC
  • Бронзовая медаль 216
Ну я прописал INDEXENT( player ) скомпилировал перестал работать прожектор если ему задать дистанцию ,но это фигня без дистанции работает.
Энтити перестали пропадать у клиента.:)
Самое главное то что фпс теперь такой же как без этого кода:( что получается он не работает или работает неправильно?!
Я кажется понимаю в чем проблема, но не знаю, как это исправить. Видимо идет проверка по какому-то из клиентов, и если хоть одному отправились данные об энтитях, то отправятся всем...но это не точно. Не знаю, тут надо думать и тестировать... Попробую запустить мультиплеер у себя на досуге, посмотрю.

В любом случае, для синглплеера это можно оставить.
 

Aynekko

Маппер
Команда форума
Супер Модератор
07.06.2010
3 629
28
  • Золотая медаль RC
  • Бронзовая медаль 216
что получается он не работает или работает неправильно?!
Кажется, я решил проблему. Вот новый код:
C++:
if( pEntity->pev->fadedistance > 0 )
        {
            Vector CenterOffset = (ent->v.mins + ent->v.maxs) / 2.f;
            Vector EntOrigin = ent->v.origin + CenterOffset;
            if( fabs( (host->v.origin - EntOrigin).Length() ) > ent->v.fadedistance + 255 )
                return 0;
        }
Проверь, пожалуйста. Я протестил у себя (сделал сервак), вроде бы работает. Как оказалось, host это тот самый клиент, которому отсылаются данные. И никакой INDEXENT не нужен.
 
  • Like
Reactions: Next Day

Aynekko

Маппер
Команда форума
Супер Модератор
07.06.2010
3 629
28
  • Золотая медаль RC
  • Бронзовая медаль 216
Нашлась недоработка, связанная с триггер_камерой (после последнего обновления, что я кидал). У меня на карте игрок находится далеко и начинает играться сценка камерой. И тут выясняется, что энтитю не видно. Сам клиентский рендер энтитю-то может показать, но он ведь теперь о ней ничего не знает. Ведь проверка дистанции между игроком и энтитей показала, что ее отправлять не нужно. Надо думать. Пока есть предположение на скорую руку, что нужно подсовывать координаты этой самой камеры, а у игрока ставить какой-то флажок, что он сейчас юзает камеру. Сложна. Будем разбираться.
P.S. очень рекомендую для теста завести квар типа sv_fade_props на сервере и ту функцию в последнем обновлении обернуть в него. Так тестировать удобнее.
 

Aynekko

Маппер
Команда форума
Супер Модератор
07.06.2010
3 629
28
  • Золотая медаль RC
  • Бронзовая медаль 216
Фикс получился. Только он получился очень громоздким. Нужно редактировать игрока и триггер_камеру. Если кому-то нужно, вот фикс. К сожалению, тут я не могу гарантировать, что в функционале камеры не сломается что-то еще, поэтому на свой страх и риск. В ином случае лучше просто воздержитесь от обновления тутора (UPDATE 26.07.2021 в первом посте). Все, что до этого, можно использовать.

Итак. Делаем все на сервере. Тут все объяснять дотошно не буду - если вы уже осилили основу тутора, здесь проблем точно не возникнет :)
player.h, class CBasePlayer, добавляем:
C++:
string_t CameraEntity;
Vector CameraOrigin;
Сюда будем копировать имя и координаты камеры, которую в данный момент юзает игрок.
Далее в player.cpp, кидаем в сейврестор:
C++:
DEFINE_FIELD( CameraEntity, FIELD_STRING ),
DEFINE_FIELD( CameraOrigin, FIELD_VECTOR ),
В этом же файле, в PostThink игрока, кидаем куда-нибудь в середину функции:
C++:
if (CameraEntity == NULL)
    CameraOrigin = GetAbsOrigin();
Тут понятно - если камеры нет, то значит игрок смотрит из своего оригина (на самом деле это не совсем так, но в данном случае это не важно).

Далее - triggers.cpp, ищем класс камеры CTriggerCamera.
В конце функции Use, перед комментарием "// follow the player down", добавляем:
C++:
// now copy the name to player who's using us
if( pev->targetname != NULL )
    ((CBasePlayer*)((CBaseEntity*)m_hPlayer))->CameraEntity = pev->targetname;
В самом начале функции FollowTarget, после "if( m_hPlayer == NULL ) return;" добавляем код
C++:
// player's camera has changed, switch off
    if (pev->targetname != NULL)
    {
        if (((CBasePlayer*)((CBaseEntity*)m_hPlayer))->CameraEntity != pev->targetname)
        {
            SetLocalVelocity(g_vecZero);
            SetLocalAvelocity(g_vecZero);
            DontThink();
            m_state = 0;
            return;
        }
    }

    // update this to player
    // BUGBUG m_iszViewEntity NOT accounted
    ((CBasePlayer*)((CBaseEntity*)m_hPlayer))->CameraOrigin = GetAbsOrigin();
Тут немножко поясню. Первое условие проверяет, какое имя камеры записано у игрока. Когда игрок юзает какую-либо камеру, это имя перезаписывается. То есть если оно не совпало, значит камеру нужно выключить - игрок уже пользуется другой камерой. Заодно пофиксился давний баг, который меня давно бесил - камера продолжала работать, если игрок не выключил ее, а просто переключился на другую.
Ну а строчка после - раз уж условие не выполнилось, то нужно игроку обновить координаты камеры. Ведь камера может быть прикреплена парентом, поэтому это нужно делать постоянно. И как раз от этого оригина мы и будем далее делать отсчет. Но пока это еще не все.
В функции Stop, внутрь условия if( m_hPlayer != NULL ) (оно в самом начале) добавляем еще одну строчку:
C++:
((CBasePlayer*)((CBaseEntity*)m_hPlayer))->CameraEntity = NULL;
Раз уж игрок завершил работу с камерой вручную, обнулим у него имя камеры.
С камерой все. А теперь тот самый обновленный код, который нужно добавить в AddToFullPack.
C++:
if( pEntity->pev->fadedistance > 0 )
        {
            Vector CenterOffset = (ent->v.mins + ent->v.maxs) / 2.f;
            Vector EntOrigin = ent->v.origin + CenterOffset;
            
            CBasePlayer* pPlayer = (CBasePlayer*)GET_PRIVATE(host);
            Vector HostOrigin = pPlayer->CameraOrigin;
            if( fabs( (HostOrigin - EntOrigin).Length() ) > ent->v.fadedistance + 255 )
                return 0;
        }
Вроде бы все. Тестируйте, проверяйте.
 

Aynekko

Маппер
Команда форума
Супер Модератор
07.06.2010
3 629
28
  • Золотая медаль RC
  • Бронзовая медаль 216
Поправка сервера. Отредактировал первый пост.
ВАЖНО: перед этим желательно сделать фикс из предыдущего поста! Иначе trigger_camera не будет работать правильно!
Новая функция, которую нужно добавить на сервер перед функцией AddToFullPack:
C++:
//===========================================================================
// IsDistanceCulled: if the entity is far enough, we don't send it to client.
//===========================================================================
bool IsDistanceCulled(edict_t* host, CBaseEntity* pEntity)
{
    if( !host || !pEntity )
        return false;

    if( pEntity->pev->iuser4 <= 0 )
        return false;

    Vector CenterOffset = (pEntity->pev->mins + pEntity->pev->maxs) / 2.f;
    Vector EntOrigin = pEntity->GetAbsOrigin() + CenterOffset;

    CBasePlayer* pPlayer = (CBasePlayer*)GET_PRIVATE(host);
    Vector HostOrigin = pPlayer->CameraOrigin;

    // calculate new, increased fade distance if we are zoomed
    // for FOV above 70 it is assumed that distance remains unchanged
    // NOTENOTE same stuff is going on in R_ComputeFadingDistance on client
    float FOV = pPlayer->m_iFOV;
    if (FOV <= 0) FOV = 90;
    float FOVfactor = bound(30, FOV, 70) / 70;
    int FadeDistance = pEntity->pev->iuser4 * (1 / FOVfactor);

    // NOTENOTE fadedistance + 255 is the distance where the ent is completely unseen visually
    if( fabs( (HostOrigin - EntOrigin).Length() ) > FadeDistance + 255 )
        return true;
    else
        return false;
}
Далее, в AddToFullPack после строчки if(!Entity) return 0; добавляем:
C++:
// don't send faded entites' data to clients
    if( IsDistanceCulled( host, pEntity ) )
        return 0;
==========================================================================

Зачем нужна эта функция на сервере? Дело в том, что мы отрезаем видимость только на клиенте, но сервер все еще считает, что игрок видит все эти энтити. И отправляет все данные о них клиенту. Как ни странно, это ОЧЕНЬ сильно влияет на фпс. Смотрите сами:
128455
128456


Найдите здесь одно отличие :) Все дело в том, что внутри этих коробок суммарно находится 1980 моделей. А я отлетел далеко за карту и они не рисуются. Но сервер считает иначе.
А функция выше просто отрежет их вообще.
Если хотите, можете вообще не использовать клиентскую функцию. Но тогда энтити будут появляться резко из воздуха, а не плавно. Это не очень красиво.
 
  • Like
Reactions: Next Day

Aynekko

Маппер
Команда форума
Супер Модератор
07.06.2010
3 629
28
  • Золотая медаль RC
  • Бронзовая медаль 216
Вчера с товарищем NextDay провели эксперимент. Он дал отличную идею отрезать энтити позади игрока. Сам рендер это уже делает - это понятно. Но тут я подумал, а что на сервере происходит в этот момент? Как выяснилось, в AddToFullPack инфа об энтитях все равно посылается клиенту, даже если они сзади него. Но это и правильно - иначе, отвернувшись, мы не услышим летящую ракету, другого игрока или монстра. А что насчет статических моделей, спрайтов и прочего несущественного добра? В общем, не долго думая, я сделал проверку на положение взгляда игрока на сервере и отрезал все, что сзади (а точнее, только статические модели).


На видео тестовая карта с 2000 моделей. Даже если я полностью отвернусь, я все равно получаю 80 фпс. Включив консольную команду с моей проверкой, фпс поднимается до 1000. Если повернусь, то модели все на месте. Как говорится - если нет разницы, зачем платить больше? Зачем вообще клиенту знать о статических моделях или простых спрайтах сзади него?
Прирост получился очень неплохой. Но, как мне подсказал SNMetamorph, нужно все же искать, отчего вообще идет просад фпс. Где-то на клиенте? В движке? Мы с NextDay думаем, что это банально из-за огромного массива информации от энтитей - сервер ведь думает, что игрок находится в едином пространстве с моделями и отправляет ему всю инфу.
 

KorteZZ

Возрождение...
18.10.2009
892
33
  • Золотая медаль 113
Классная штука. Реально, можно таким образом хорошо детализировать окружение разными небольшими моделями, пропами.
 
  • Like
Reactions: Next Day

Aynekko

Маппер
Команда форума
Супер Модератор
07.06.2010
3 629
28
  • Золотая медаль RC
  • Бронзовая медаль 216
Классная штука. Реально, можно таким образом хорошо детализировать окружение разными небольшими моделями, пропами.
Да. В густонаселенных моделями местах (как например у меня в био-лабах с кучей деревьев и кустов) фпс вырос на сотню.
 
  • Like
Reactions: Next Day

ncuxonaT

Well-known member
05.05.2013
1 196
46
48
Если есть динамическое освещение с тенями, то при таком подходе будут пропадать тени от объектов, когда игрок от них отворачивается.
 

Донат - Хостинг

Итого
200.00 $
Цель
600.00 $

Доноры Красавчики

Пользователи онлайн

Нет пользователей онлайн.