Manuals
Manuals




This translation is community contributed and may not be up to date. We only maintain the English version of the documentation. Read this manual in English

Оптимізація швидкодії під час виконання

Перш ніж оптимізувати гру, щоб вона працювала зі стабільно високою частотою кадрів, потрібно знати, де її вузькі місця. Що насправді займає найбільше часу в кадрі вашої гри? Рендеринг? Ігрова логіка? Граф сцени? Щоб з’ясувати це, рекомендовано використовувати вбудовані інструменти профілювання. Скористайтеся екранним або вебпрофайлером, щоб виміряти продуктивність гри, а потім вирішити, чи потрібна оптимізація та що саме оптимізувати. Коли ви краще зрозумієте, на що витрачається час, можна починати розв’язувати проблеми.

Скорочення часу виконання скриптів

Скорочувати час виконання скриптів потрібно, якщо профайлер показує високі значення в області Script. Загалом, звісно, слід намагатися виконувати якомога менше коду в кожному кадрі. Виконання великого обсягу коду в update() та on_input() у кожному кадрі, імовірно, впливатиме на продуктивність гри, особливо на малопотужних пристроях. Ось кілька рекомендацій:

Використовуйте реактивні підходи до написання коду

Не перевіряйте постійно наявність змін, якщо можете отримати зворотний виклик. Не анімуйте щось вручну й не виконуйте завдання, яке можна доручити рушію (наприклад, використовуйте go.animate)() замість анімації вручну).

Зменшення потреби у збиранні сміття

Якщо ви створюєте багато об’єктів із коротким часом існування, як-от таблиць Lua, у кожному кадрі, це зрештою запустить збирач сміття Lua. Це може проявлятися як невеликі затримки/стрибки часу кадру. Повторно використовуйте таблиці, де це можливо, і намагайтеся уникати створення таблиць Lua всередині циклів та подібних конструкцій.

Заздалегідь хешуйте ідентифікатори повідомлень і дій

Якщо ви обробляєте багато повідомлень або подій введення, рекомендовано заздалегідь хешувати рядки. Розгляньте цей фрагмент коду:

function on_message(self, message_id, message, sender)
    if message_id == hash("message1") then
        msg.post(sender, hash("message3"))
    elseif message_id == hash("message2") then
        msg.post(sender, hash("message4"))
    end
end

У наведеному прикладі хешований рядок створюватиметься заново щоразу, коли надходить повідомлення. Це можна поліпшити, створивши хешовані рядки один раз і використовуючи їхні хешовані версії під час обробки повідомлень:

local MESSAGE1 = hash("message1")
local MESSAGE2 = hash("message2")
local MESSAGE3 = hash("message3")
local MESSAGE4 = hash("message4")

function on_message(self, message_id, message, sender)
    if message_id == MESSAGE1 then
        msg.post(sender, MESSAGE3)
    elseif message_id == MESSAGE2 then
        msg.post(sender, MESSAGE4)
    end
end

Віддавайте перевагу URL і кешуйте їх

Передавати повідомлення або в інший спосіб адресувати ігровий об’єкт (game object) чи компонент (component) можна, задавши ідентифікатор як рядок, хеш або URL. Якщо використано рядок чи хеш, усередині рушія його буде перетворено на URL. Тому рекомендовано кешувати URL, які використовуються часто, щоб досягти якнайкращої продуктивності системи. Розгляньте такий приклад:

    local pos = go.get_position("enemy")
    local pos = go.get_position(hash("enemy"))
    local pos = go.get_position(msg.url("enemy"))
    -- do something with pos

У всіх трьох випадках буде отримано позицію ігрового об’єкта з ідентифікатором enemy. У першому та другому випадках ідентифікатор (рядок або хеш) перед використанням буде перетворено на URL. Отже, для якнайкращої продуктивності краще кешувати URL і використовувати кешовану версію:

    function init(self)
        self.enemy_url = msg.url("enemy")
    end

    function update(self, dt)
        local pos = go.get_position(self.enemy_url)
        -- do something with pos
    end

Скорочення часу рендерингу кадру

Скорочувати час рендерингу кадру потрібно, якщо профайлер показує високі значення в областях Render і Render Script. Ось кілька речей, які варто врахувати, коли ви намагаєтеся скоротити час рендерингу кадру:

  • Зменште кількість викликів малювання (draw calls) — докладніше про це читайте в цьому дописі на форумі
  • Зменште надлишкове малювання (overdraw)
  • Зменште складність шейдерів — прочитайте про оптимізацію GLSL у цій статті Khronos. Також можна змінити стандартні шейдери, які використовує Defold (вони розташовані в builtins/materials), і вибрати нижчу точність там, де шейдеру не потрібна highp. У кроскомпільованих шейдерах GLSL ES для значень із рухомою крапкою за замовчуванням використовується mediump, а для цілих чисел — highp; ці значення за замовчуванням можна змінити в розділі Shader налаштувань проєкту. Явно задані кваліфікатори для окремих змінних мають пріоритет. Див. документацію про точність шейдерів.

Зменшення складності графа сцени

Зменшувати складність графа сцени потрібно, якщо профайлер показує високі значення в області GameObject, а точніше — для вимірювання UpdateTransform. Ось що можна зробити:

  • Відсікання (culling) — вимикайте ігрові об’єкти (та їхні компоненти), якщо вони наразі невидимі. Спосіб визначення видимості значною мірою залежить від типу гри. У 2D-грі може бути достатньо завжди вимикати ігрові об’єкти, розташовані за межами прямокутної області. Для виявлення цього можна скористатися фізичним тригером або розподілити об’єкти по групах. Коли ви знаєте, які об’єкти потрібно вимкнути чи ввімкнути, надішліть повідомлення disable або enable кожному ігровому об’єкту.

Відсікання за пірамідою видимості

Скрипт рендерингу може автоматично пропускати рендеринг компонентів ігрових об’єктів, які перебувають за межами визначеного обмежувального паралелепіпеда (піраміди видимості). Докладніше про відсікання за пірамідою видимості (frustum culling) читайте в посібнику з конвеєра рендерингу.

Оптимізація для окремих платформ

Android Device Performance Framework

Android Dynamic Performance Framework — це набір API, які дають змогу іграм безпосередніше взаємодіяти із системами керування живленням і температурою пристроїв Android. Можна відстежувати динамічну поведінку систем Android та оптимізувати продуктивність гри на рівні, який можна підтримувати тривалий час без перегрівання пристроїв. Використовуйте розширення Android Dynamic Performance Framework, щоб відстежувати й оптимізувати продуктивність вашої гри на Defold для пристроїв Android.