Перейти к содержанию
Arkada

Как оптимизировать моды на S.T.A.L.K.E.R.

Рекомендуемые сообщения

 

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

Спойлер
Спойлер
  1. Память безусловно играет большую роль. Особенно на высоких настройках графики. Но в скриптах безусловно есть функции, которые не используются. Их следует просто удалить.
  2. _G. Глобальная область видимости. Обычно в этот скрипт добавляют функции, которые используются повсеместно.
    Но там могут быть функции, которые используются только в одном скрипте, возьмём к примеру utils. И всё. Эта самая функция видна в каждом скрипте, т.к. она помещена в _G. А зачем? Зачем помещать в _G, если эта функция используется лишь в одном файле? Функцию следует переместить в тот файл, к примеру в utils.
    Также нужно сделать и с глобальными переменными.
  3. Локальные и глобальные объекты. Разные вещи, всё-таки. Некоторые скрипты содержат в себе глобальные переменные, например скрипт modules. Другие скрипты во время своей работы могут обратиться к какой-то глобальной переменной из modules.
    Но, везде но... в скрипте создаётся глобальная переменная, но она используется только в этом скрипте. То есть, по сути она используется как локальная, но она глобальная. Доступ к глобальным переменным происходит немного медленнее, чем к локальной. В данном случае необходимо все такие глобальные переменные, которые в этом скрипте, сделать локальными.
  4. Функции и локальные функции (local function ()). Первое - это те функции, к которым можно обратиться из других скриптов, глобальные функции. Абсолютно в каждом скрипте есть глобальная функция, и это нормально. Но есть те функции, которые как и переменные (тавтология), используются только в данном файле, но они объявлены как глобальные. Повторюсь,
    Цитата

    Доступ к глобальным переменным происходит немного медленнее, чем к локальной.


    это касается и функций, поэтому эти функции должны быть объявлены как локальные.
  5. Каждый символ в строке весит 1 байт. Например, пустая строка "" весит 1 байт (в конце всегда нуль-терминатор, \0).
    Поэтому не рекомендую вам делать длинные названия чего-либо (их названия - это строки), ибо займёт много памяти, особенно, если это какой-нибудь класс, который используется у нескольких объектов.
Спойлер
  1. Цикл for i = 0, 65535 do. Это цикл, перебирающий все спавн-объекты в игре. Много где используется.
    Итак, первое замечание, это конец цикла - итерация №65535. Это максимально допустимое число типа unsigned short (int), и это максимум спавн-объектов, который может быть в игре. В игре по умолчанию объект с ID 65535 это "Invalid". От него ничего нельзя получить, никаких данных. Просто это сигнализирует о том, что дальше объектов быть не может, этот последний.
    Следовательно, необходимо делать не 65535 итераций, а 65534.
    Второе замечание, ID, с которого начинается итерация, ноль. Ноль это всегда ID игрока, абсолютно всегда, так как самым первым на уровне создаётся и загружается именно игрок. В некоторых случаях, например, поиск и удаление каких-то предметов с помощью такого цикла. В таком случае, актёр - не предмет, следовательно он нам вообще не нужен, и итерацию нужно начинать с единички. Вот вполне вероятно, что ID 1 - это предмет.
  2. Балячка сталкерских скриптов, - передача аргумента в качестве объекта, от которого будет взят только один параметр. Зачем передавать целый объект, если используется один лишь его параметр, можно передать тот самый параметр.
    Спойлер
    
    
    
    --КАК НЕ НАДО ДЕЛАТЬ!!!
    local function IsActor(obj)
    	return obj:id() == 0
    end
    --представим, что мы откуда-то взяли НПС, CGameObject* (именно указатель на него!)
    print(IsActor(who)) --результат неизвестен
    
    --КАК НАДО ДЕЛАТЬ
    local function IsActor(obj_id)
    	return obj_id == 0
    end
    --представим, что мы откуда-то взяли НПС, CGameObject* (именно указатель на него!)
    print(IsActor(who:id())) --результат неизвестен

     

    Думаю, вы уловили суть.

  3. Удалите все функции, которые вызываются, но в результате они ничего не делают. Например, функция printf и её аналоги (print_table,store_table). Это - лишние действия, которые затрачивают ресурсы компьютера в результате на ничего. Зачем? Каждой программе безусловно нужно тестирование и отладка, printf та самая функция.
    Но дело тут в том, что она просто не нужна. Если движовая функция log доступна, то printf выводит в лог кучу информации. Которая модмейкеру, уверен, не нужна. Если модмейкеру нужно что-то отладить, исправить какой-то баг, то ОН САМ может в нужном месте запихнуть вывод в лог, а потом закомментировать. И ещё, иногда это забывают делать, и в итоге, в логе мода, который выпустили в открытую сеть, много ненужной инфы. И в некоторых случаях это только затрудняет поиск причины вылета.

  4. Создание таблицы, и после её создания сразу же внесение данных. Это смотрится красиво, но код от этого замедляется ох как хорошо. Таких таблиц вообще не следует допускать. Lua проще записать всю информацию в таблицу на этапе её создания, чем после неё.

    
    
    --ТАК НЕ ДОЛЖНО БЫТЬ!!!!
    local t = {}
    t[1] = false
    t[2] = true
    t[3] = false
    
    --ВОТ ТАК ДОЛЖНО. Эквивалетно прошлому примеру, но побыстрее.
    local t =
    {
    	[1] = false,
      	[2] = true,
      	[3] = false
    }
  5. Постоянная проверка на неравенство значений. Это лишнее!
    По факту ведь ничего не изменится, если такой код
    
    
    --Допустим это функция вызывается из bind_stalker.actor_binder:update(dt)
    local lst = 10
    function update(dt)
    	--съедает фпс
    	if dt ~= lst then
    		lst = dt
    	end
    end

    можно переделать в код вида

    
    
    --Допустим это функция вызывается из bind_stalker.actor_binder:update(dt)
    local lst = 10
    function update(dt)
    	--ускорение примерно в 3,5 раза за удаление ОДНОГО неравенства
    	lst = dt
    end

    который будет быстрее.

Спойлер
  1.  Соединения строк. В Lua можно со строкой соединять и число, без использования функции tostring. Быстрее работает тот код, который без использования tostring.
    
    
    local c = "math"..tostring(7) --медленнее
    --Эквивалентно
    local c = "math"..7 --быстрее

     

  2. Математические операции со строками. Да, именно так, но есть одно но:
    
    
    --Такой код будет работать
    local c = "70"
    c = c - 5
    c = c + 2
    c = c * 2
    c = c / 4
    print(c) --выведет 33.5
    
    --ТАКОЙ КОД НЕ БУДЕТ РАБОТАТЬ
    local c = "70f"
    c = c - 5 --выведет ошибку
    c = c + 2
    c = c * 2
    c = c / 4
    print(c)
    --[[
    lua: main.lua:2: attempt to perform arithmetic on a string value (local 'c')
    stack traceback:
    	main.lua:2: in main chunk
    	[C]: in ?
    ]]

    Если в строке есть символы, не определяющиеся как число (буквы, например) - то будет ошибка в коде. Тогда в строке должны быть только цифры (точка, минус).
    Работает и с шестнадцатеричной системой исчисления (0xff).
    Даже если в строке целое число, то в результате действия с любыми математическими операторами, встроенными в Lua, оно преобразуется во float.

 


Спойлер

Мелочи, которые тоже придают прирост ФПС.

  1. Старайтесь избегать деления. Да, именно так. Процесс деления происходит немного медленнее, чем процесс умножения. Например:
    Спойлер
    
    
    local test = 150
    test = test * 0.1 --В данном случае эквивалентно test = test / 10
    print(test) --Выведет 15

    Список замен:
    /10 = * 0.1
    /100 = * 0.01
    /1000 = * 0.001 и т.п.
    /2 = * 0.5
    /4 = * 0.25
    /5 = * 0.2
    /8 = * 0.125

  2. Не используйте степень. Вообще. Когда я проводил тесты, то просто поразился результату. Например, если какое-то число умножать само на себя два раза, то это будет в полтора раза быстрее, чем возвести в квадрат.
  3. Удалите лишние аргументы из функции, которые не используются, но передаются. Например:
    
    local function test(param) -- param не используется!!! но передаётся
      print("Test?")
    end
    test(true)

    В данном случае нужно удалить аргумент param в функции, и убрать его при передаче. Зачем лишний раз передавать "ничего"?

  4. Удалите пустые блоки кода. Даже в оригинальных скриптах они есть.
     

    
    function test()
       return math.random(3)
    end
    --ПУСТОЙ БЛОК КОДА!!!
    if test() == 2 then
      --print(true)
    end
    
    --НУЖНО ЗАМЕНИТЬ НА
    --if test() == 2 then
      --print(true)
    --end
    
    --ИЛИ ВОВСЕ УДАЛИТЬ!
  5. Если вдруг какой-то файл после каких-то действий не будет использоваться, то лучше его удалить из памяти, ведь он в дальнейшем не пригодится. Сделать это можно так:
    
    _G["имя скрипта"] = nil
    --или (эквивалентно)
    _G.имя_скрипта = nil

    Или, если похожая ситуация с функцией (например, каллбэк на старт игры)

    
    имя_скрипта["имя_функции"] = nil
    --или (эквивалентно)
    имя_скрипта.имя_функции = nil
  6. Умножить, разделить сложить и вычесть все известные числа.
    
    local a = 12*12
    --Сделать так. Умножить известные числа
    local a = 144

     

 

Изменено пользователем liner
  • Лайк 1
  • Жму руку 2
  • Хабар 2
  • Спасибо 3

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
 

1)Никогда не ставьте 8К текстуры в свой мод
2)Отключайте использование 0 ядра

  • Мастер! 1
  • Смех 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
 

Я тут вычитал в описании к одному моду на Anomaly, что якобы движок сталкера подгружает при работе и те файлы, которые лежать в геймдате, но нигде не используются. Это правда? 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
 

baraholschik Я то откуда знаю. Спросите у разработчиков аномали.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
 
3 часа назад, baraholschik сказал:

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

А зачем в геймдате нужны файлы, которые нигде не используются? )))

И да, тут нужно уточнить, какие именно файлы, файлы оригинальной игры, или вообще левые файлы.

Левые файлы по любому никак не будут грузиться. А вот оригинальные файлы игры, они и так всегда грузятся(читаются), хоть они и не используются модом. Но вопрос, что они делают в геймдате, они в самой игре и так есть)))

Изменено пользователем alex5773
  • Мастер! 1

На ap-pro с 2010 года.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
 

alex5773 И причем здесь эта тема? Оффтопите. Не пишите здесь об этом.

  • Мастер! 1
  • Смущение 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
 

liner тема здесь к месту хотя бы потому что, возможно, очистка геймдаты от ненужного хлама может сказаться на оптимизации мода. А при не аккуратном моддинга завалить папки недействующими конфигами, моделями и текстурами проще простого. Вот и хочется знать, может ли движок обрабатывать эти ненужные файлы. Речь не столько про Аномалию, сколько про COC например

  • Хабар 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
 

liner, так удалите, не против. 

33 минуты назад, baraholschik сказал:

может ли движок обрабатывать эти ненужные файлы

Нет, не нужные он не читает вообще. 

Каким образом он будет читать то, до чего нет пути.

Можешь в мод хоть весь мусор скинуть. Просто размер будет больше.

А вот мусор в скриптах, которые используются, это другое дело.

  • Мастер! 1

На ap-pro с 2010 года.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
 

baraholschik Если подумать, допустим:
В system.ltx включаются файлы (директива include). И допустим мы включили специально лишний конфиг, в котором много лишних секций.
В результате, если мы хотим вычитать какую-то строчку из какой-то секции, то итераций будет больше, т.к. ещё будет проверяться новый конфиг. Думаю вы поняли к чему я.
Но вот просто валяющиеся текстуры не нагружают игру, я думаю, и если они не занесены в список заранее загружаемых текстур (кэш текстур).
alex5773 Удалять могут только модераторы.

  • Мастер! 1
  • Хабар 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
 

Закину свои 5 копеек. r3_sm_minmax следует отключать. Из-за неё на DX10 и выше имеется просадки ФПС со временем. На DX10 и выше у нас есть доступ к волшебному ключику запуска -no_staging, благодаря которому мы можем отключить кеширование текстур в оперативную память, тем самым разгружая место под что-то более важное. Многопоточность. Как известно GSC пытались реализовать многопоточность (особенно это заметно на бенчмарк сборке, но и в релизной версии она тоже есть, хоть и порезана). Проблема в том, что на многоядерных системах этот многопоток хуже только делает. Но решение есть! Используя ключик -max-threads 1-... можно задавать количество потоков помощников. В идеале ставить 1, чтобы этих потоков вообще небыло, но можно попытаться подобрать идеальное значение. Главное не делать его слишком большим.

Изменено пользователем Hozar_2002
  • Лайк 2
  • Жму руку 1
  • Спасибо 1


image.png.489a34a67081676c25779ea216ba3788.png


 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
 

Еще сильно просаживают фпс скрипты подключенные на апдейт актора. А если таких скриптов много подключено в bind_stalker.script в actor_binder:update(delta) то реально будет замедление. Ставьте таймеры, да будет выполнятся проверка таймера но не весь код скрипта. Так например у меня погода обновляется раз в час так зачем проверять условия в скрипте по несколько десятков раз в секунду я поставил раз в минуту. и таких скриптов оказалось 4 штуки. Для некоторых достаточно раз в секунду почти для всех четыре раза в секунду. Результат удивил производительность повысилась фпс вырос. Особенно это будет актуально для слабых машин. Примеры испоьспользования таймеров можно посмотреть в огср в огсе модах.

  • Лайк 1
  • Хабар 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
 

Может нужно просто поменять использование памяти движку? Место 512 мб хотя бы на 1гб

И движок перенести на 64x


Дополнено 0 минут спустя

Ну и к тому же сектора делать для локаций

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
 
10 часов назад, Stalkervernite сказал:

Место 512 мб хотя бы на 1гб

х32 движок может вместить до 4гб ОЗУ.

10 часов назад, Stalkervernite сказал:

И движок перенести на 64x

Если в моде нету 4к текстур и огромных локаций, то смысла в x64 нет, т.к. такой мод не будет жрать более 4гб оперативы.

Для нормальной оптимизации нужно переходить на ЗП с движком IX-Ray. Если у вас ТЧ или ЧН, я вам соболезную точно также используйте IX-Ray, но потом переходите на ЗП.

  • Жму руку 2
  • Клоун 5

бывший модоел

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
 

Bruh...

Ладно, давайте с основ. В xray большая болезнь модов - слабы компы юзеров. Основные проблемы - это подгрузка данных. Слабые харды плюют и помирают на крупных модах.


1. Выучите что такое UV и не плодите "уникальные текстуры" на каждый объект. 
2. Оптимизируйте меши. Размер играет роль 
3. Черезмерная детализация динамики вообще не имеет смысла без правки шокера по скиннингу (всё равно всё в шорт режется) 
4. Финальный мод пакуйте в .db. Архивы xray хавает лучше, чем n-тысяч файлов в геймдате. 

-- 
Конфиги/скрипты - на ваше усмотрение. Первые инциализируются в общую кучу при запуске (а в том же OGSR там unordered map, что хранит ключи в хеш-виде, так что там итерация почти моментальная), вторые при обращении загружаются в машину и там живут 

Следующая проблема - GPU 

1. Шейдерые правки и фичи без возможности отключения на стороне юзера - проблема как по части регуляции производительности на стороне пользователя, так и его комфорт 
2. Огромные текстуры - пощадите GPU. Двиг не умеет в "виртуальные текстуры", он слишком стар. 
3. Делайте лоды, сектора и порталы. XRay без них плохо 

И самое грустное - CPU 

Двиг живёт в полтора потока. Не надо завешивать все скрипты на апдейт. Есть коллебки под разные ситуации. Избегайте лишних операций. Луа компилируется в реалтайме и код ваш оптимизирует он очень плохо (почти никак). 

  • Мастер! 1
  • Жму руку 1
  • Хабар 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
 
8 часов назад, xrLil Batya сказал:

IX-Ray

Так усердно вылизывать ASS даже Лана Роудс в былые годы славы не могла, а ты могёшь, красавчик.

  • Дурка 1
  • Смех 2
  • Клоун 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
 
16 минут назад, no_data228 сказал:

Так усердно вылизывать ASS даже Лана Роудс в былые годы славы не могла, а ты могёшь, красавчик.

У тебя тоже самое, но с огсром :)

  • Жму руку 1
  • Смех 2

бывший модоел

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
 

xrLil Batya даже не знаком с ними лично... Нигде не писал что надо его использовать, так что твою стрелочку смешно читать, пупс)

  • Дурка 1
  • Клоун 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
 
5 минут назад, no_data228 сказал:

даже не знаком с ними лично...

Как это не знаком? Не притворяйся, я знаю, что ты очередной твинк-аккаунт houdini.

  • Жму руку 1
  • Смех 2

бывший модоел

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
 

В циклах убирайте local за пределы цикла, проверил очень хорошо ускоряется.

local obj
for id=0, 65534 do
  obj = level.object_by_id(id)
  if obj then
    ...
  end
end

  

Ещё бы реализовать метод search_by_id(number) пространстве level, тут уже оптимизация на 5-10 миллисек.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
 

Как запаковать gamedata в .db/.xdb? чтобы в patches закинуть и чтоб она читалась самой последней:
ресурсы игры > патчи gsc > мод .db > моя геймдата.db

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Для публикации сообщений создайте учётную запись или авторизуйтесь

Вы должны быть пользователем, чтобы оставить комментарий

Создать учетную запись

Зарегистрируйте новую учётную запись в нашем сообществе. Это очень просто!

Регистрация нового пользователя

Войти

Уже есть аккаунт? Войти в систему.

Войти

  • Последние посетители   0 пользователей онлайн

    Ни одного зарегистрированного пользователя не просматривает данную страницу