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

Как оптимизировать моды на 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.  
Спойлер
  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

"Победа - это еще не всё, всё - это постоянное желание побеждать" - Винс Ломбарди.
"Ваше время ограничено, не тратьте его, живя чужой жизнью" - Стив Джобс.
Global Modification. Clear Sky: Reload

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


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

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

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


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

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

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

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

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

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

Войти

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

Войти

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

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