Для получения триального ключа
заполните форму ниже
Team License (базовая версия)
Enterprise License (расширенная версия)
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

Запросите информацию о ценах
Новая лицензия
Продление лицензии
--Выберите валюту--
USD
EUR
RUB
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

Бесплатная лицензия PVS-Studio для специалистов Microsoft MVP
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

Для получения лицензии для вашего открытого
проекта заполните, пожалуйста, эту форму
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

Мне интересно попробовать плагин на:
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

Ваше сообщение отправлено.

Мы ответим вам на


Если вы так и не получили ответ, пожалуйста, проверьте папку
Spam/Junk и нажмите на письме кнопку "Не спам".
Так Вы не пропустите ответы от нашей команды.

>
>
>
Зачем разработчикам игр на Unity исполь…

Зачем разработчикам игр на Unity использовать статический анализ?

11 Май 2022

С годами стоимость создания игр стала больше, вырос их масштаб, а следовательно, и их кодовая база. Разработчикам становится всё сложнее уследить за ошибками. А забагованная игра влечёт финансовые и репутационные убытки. Как же с этим может помочь статический анализ?

0945_Why_should_Unity_game_developers_use_static_analysis_ru/image1.png

Введение

Мы часто пишем статьи про проверку проектов с разбором ошибок из них. Сегодняшняя статья также будет включать обзор ошибок в коде, однако главная тема — обсуждение насущных проблем в сфере разработки игр. В основном мы будем говорить про разработку под Unity, но многие моменты актуальны и для программистов из других сфер. Главными темами будут возрастающая стоимость игр, репутация компаний-игроделов и статический анализ.

Стоимость создания игр

Стоимость разработки игр с каждым годом растёт. Как следствие – дороже становятся и сами игры. Давайте разбираться, почему же так происходит.

В 2020 году произошло увеличение цены за AAA-тайтл на $10. Ранее цена была на уровне $60 и была сформирована ещё в 2000-x. Естественно, игровые студии понимают, что во многих странах покупательская способность людей не растёт, а в некоторых даже падает. Если ещё поднять стоимость игр, то их просто не будут покупать. В итоге возможны два варианта развития событий:

  • цену на игры всё же поднимают. Это скажется на количестве проданных копий;
  • цену оставляют на том же уровне или немного увеличивают. В таком случае будет страдать качество, ведь компании не будут работать себе в убыток.

Так почему же из года в год бюджеты игр растут? Чтобы ответить на этот вопрос, нужно спросить себя: "А стал бы я покупать игру, которая ничем не отличается от прошлогодней?". Думаю, многие ответили бы "нет". Разработчики вынуждены делать игры всё масштабнее, чтобы удивлять игроков.

Вы можете задать логичный вопрос: "А как сильно возросла стоимость создания игр?". Для ответа на него предлагаю обратиться к статистике. Мне удалось найти график бюджетов игр до 2017 года. В этих данных исключены расходы на маркетинг, то есть отображена только стоимость разработки.

0945_Why_should_Unity_game_developers_use_static_analysis_ru/image2.png

Из графика выше видно, что примерно каждые 10 лет стоимость разработки растёт в 10 раз. Причём в настоящее время цифры весьма внушительные. Кстати, есть интересный свежий пример.

Возьмём знаменитый Cyberpunk 2077, который имел примерный бюджет в $313 млн. Данная цифра содержит в себе расходы на продвижение игры. Обычно маркетинговые расходы меньше или равны расходам на разработку. Но даже если мы разделим общий бюджет пополам, то всё равно получим огромную сумму.

Стоит отметить, что игра вышла довольно сырой и имела много багов. Думаю, что её бюджет вырос уже довольно сильно, учитывая то, что игру продолжают доделывать уже 2 года и готовят к ней дополнения. Подобная деятельность называется пост-релизной поддержкой. Она необходима почти для любого крупного проекта, ведь какой смысл в игре, если после старта из неё уйдёт большинство игроков. Данный этап включает в себя создание нового контента и исправление багов, которые не получилось исправить на основном этапе разработки.

Кстати, о багах...

Ошибки и баги

Вы можете вспомнить хотя бы одну игру с багами? Да во всех играх есть ошибки.

0945_Why_should_Unity_game_developers_use_static_analysis_ru/image3.png

Конечно, эта фраза касается не только игр, но и любых других проектов. Невозможно создать большой и сложный продукт, который не содержит в себе ошибок. Над игрой, да и вообще над любой серьёзной программой, могут работать сотни людей. И все они не безупречные боги, им свойственно ошибаться.

Современные игры огромны, из-за этого искать ошибки в них в очень тяжело и дорого. Разработчикам становится всё тяжелее работать — приходится перерабатывать, а также жертвовать различными аспектами игры, чтобы закончить работу в срок.

Также несвоевременное исправление ошибок влияет на репутацию. Представьте, что ваша компания выпустила игру, в которой уйма багов. Люди так устроены, что в большей мере запоминают плохое. Не стоит растрачивать свою репутацию, которая так упорно зарабатывается, на ошибках, которых можно было легко избежать.

Статический анализ

У современных игровых студий есть целый арсенал технологий для упрощения разработки. Одной из них является статический анализ. Данная методология поиска потенциальных ошибок в исходном коде способна помочь студиям и их разработчикам найти различные проблемы и дефекты безопасности в их программах. Зачем ждать, пока баг всплывёт у игрока, если его можно исправить ещё при написании кода?

Кто-то может спросить: "А как это коррелирует с бюджетом, ценами и прочим?" Естественно, что поиск ошибок происходит в рабочее время, которое нужно оплачивать. При использовании статического анализа поиск дефектов происходит гораздо быстрее. Следовательно, освободившееся время можно использовать для наполнения мира, создания новых механик и прочего.

Стоит заметить, что большинство ошибок, совершаемых разработчиками игр, не отличаются от ошибок разработчиков из других сфер деятельности. Это можно понять, например, по нашим проверкам Open Source игр. В этих проектах постоянно находятся подозрительные места. Поэтому статический анализ будет полезен всем программистам.

Одним из инструментов, выполняющих статический анализ, является PVS-Studio. Я, как человек, причастный к разработке данного продукта, расскажу, в чём его польза для проектов на Unity.

В PVS-Studio было несколько особых доработок анализа проектов, использующих этот игровой движок. К примеру, мы занимались добавлением информации о поведении методов популярных классов из Unity. Это помогает находить больше ошибок в коде. Кстати, этой теме посвящена отдельная статья: "Как анализатор PVS-Studio стал находить ещё больше ошибок в проектах на Unity".

Также PVS-Studio учитывает и другие особенности этого движка. Например, что Unity предоставляет необычную реализацию оператора '==' для типов, которые наследуются от класса UnityEngine.Object.

С помощью PVS-Studio удалось найти ряд странностей и в коде самого Unity. Данной теме посвящены 3 публикации: статья 2016 года, статья 2018 года и совсем свежая статья 2022 года.

А как воспользоваться PVS-Studio в Unity?

Для начала у вас уже должен быть установлен анализатор и введена лицензия. Если же вы ещё этого не сделали, то в этом вам поможет данная страница.

Откройте ваш проект в Unity Hub. Далее нажмите: Assets -> Open C# Project. У вас откроется IDE, заданная в настройках редактора Unity. Она указывается здесь:

0945_Why_should_Unity_game_developers_use_static_analysis_ru/image4.png

Я буду использовать Visual Studio 2022. Чтобы проанализировать проект в данной версии IDE, можно использовать пункт меню Extensions -> PVS-Studio -> Check -> Solution.

0945_Why_should_Unity_game_developers_use_static_analysis_ru/image5.png

Более подробно почитать про использование анализатора вы можете здесь.

Примеры ошибок

Было бы неправильно написать статью про то, что при разработке игр нужно использовать статический анализ, и не привести примеров найденных анализатором ошибок. К сожалению, многие большие и популярные игры имеют закрытый код. Таким образом, мы не сможем проверить качество кода таких игр, как Ori and the Blind Forest, Superhot, Beat Saber, Rust, Firewatch и других. Выход можно найти на просторах Open Source. Для анализа я взял одну простую игру на Unity — Card-Game-Simulator. Этого проекта будет более чем достаточно для демонстрации работы анализатора.

Пример 1

private void Update()
{
  ....
  if (Inputs.IsSubmit && joinButton.interactable)
    Join();
  else if (Inputs.IsNew)
    Host();
  else if (Inputs.IsFocusBack)
    roomIdIpInputField.ActivateInputField();
  else if (Inputs.IsFocusNext)
    passwordInputField.ActivateInputField();
  else if (Inputs.IsPageVertical && !Inputs.IsPageVertical) // <=
    ScrollPage(Inputs.IsPageDown);
  else if (Inputs.IsPageHorizontal && !Inputs.WasPageHorizontal)
    ToggleConnectionSource();
  else if (Inputs.IsCancel)
    Close();
}

V3022 Expression 'Inputs.IsPageVertical && !Inputs.IsPageVertical' is always false. Probably the '||' operator should be used here. LobbyMenu.cs 159

Анализатор сообщает о том, что выражение Inputs.IsPageVertical && !Inputs.IsPageVertical всегда ложно. IsPageVertical представляет из себя свойство, которое возвращает значение типа bool.

public static bool IsPageVertical =>
  Math.Abs(Input.GetAxis(PageVertical)) > Tolerance;

Естественно, что не существует значения, при котором данное условие будет истинно. При этом чуть ниже имеется выражение с похожими свойствами. После взгляда на них становится понятно, что в указанном анализатором месте опечатка.

Скорее всего, условие должно выглядеть следующим образом:

Inputs.IsPageVertical && !Inputs.WasPageVertical

Пример 2

private bool DecodeDict()
{
  while (neededBits > 0)
  {
    int dictByte = input.PeekBits(8);
    if (dictByte < 0)
    {
      return false;
    }
    input.DropBits(8);
    readAdler = (readAdler << 8) | dictByte;
    neededBits -= 8;
  }
  return false;
}

V3009 It's odd that this method always returns one and the same value of 'false'. Inflater.cs 288

PVS-Studio указывает на то, что данный метод всегда возвращает false. Если мы взглянем на код, то увидим, что имеется только два return и оба возвращают false. Стоит отметить, что перед объявлением метода имеется комментарий:

/// <summary>
/// Decodes the dictionary checksum after the deflate header.
/// </summary>
/// <returns>
/// False if more input is needed.
/// </returns>
private bool DecodeDict()

Комментарий даёт понять, что метод DecodeDict возвращает false только в случае, если недостаточно входных данных. Фактически же метод всегда возвращает false :). Может быть и так, что метод действительно никогда не должен возвращать true, но выглядит это странно, а данный комментарий вводит в заблуждение.

Пример 3

public override int PixelWidth
{
  get
  {
#if (CORE_WITH_GDI || GDI) && !WPF
    try
    {
      Lock.EnterGdiPlus();
      return _gdiImage.Width;
    }
    finally { Lock.ExitGdiPlus(); }
#endif
#if GDI && WPF
    int gdiWidth = _gdiImage.Width;
    int wpfWidth = _wpfImage.PixelWidth;
    Debug.Assert(gdiWidth == wpfWidth);
    return wpfWidth;
#endif
#if WPF && !GDI
    return _wpfImage.PixelWidth;
#endif
#if NETFX_CORE || UWP
    return _wrtImage.PixelWidth;
#endif
#if __IOS__
    return (int)_iosImage.CGImage.Width;
#endif
#if __ANDROID__
    return _androidImage.Width;
#endif
#if PORTABLE
    return PixelWidth;                    // <=
#endif
  }
}

V3110 Possible infinite recursion inside 'PixelWidth' property. XBitmapSource.cs 97

Анализатор обнаружил потенциальную бесконечную рекурсию. Аксессор get содержит несколько директив препроцессора #if, и в последней из них свойство обращается само к себе. Если при сборке символ PORTABLE будет определён, а другие символы из директив — нет, возникнет бесконечная рекурсия.

Пример 4

public override bool Equals(object obj)
{
  Selector selector = obj as Selector;
  if (obj == null)
    return false;
  return _path == selector._path; ;
}

V3019 Possibly an incorrect variable is compared to null after type conversion using 'as' keyword. Check variables 'obj', 'selector'. PdfFormXObjectTable.cs 217

Анализатор обнаружил потенциальную ошибку, которая может привести к обращению по нулевой ссылке. Объект базового класса привели к производному с помощью as. В случае неудачного преобразования значению selector будет присвоен null. В данном случае на равенство null проверяется переменная базового типа — obj. Таким образом, при передаче в метод ссылки на объект типа Selector или нулевой ссылки, исключение выброшено не будет. В остальных случаях будет выбрасываться исключение. Обычно же ожидается, что метод в таком случае будет возвращать false. Скорее всего, стоит проверять на равенство null именно переменную selector.

Пример 5

internal PdfFormXObject(....): base(thisDocument)
{
  ....
  XPdfForm pdfForm = form;
  // Get import page
  PdfPages importPages = importedObjectTable.ExternalDocument.Pages;
  if (   pdfForm.PageNumber < 1
      || pdfForm.PageNumber > importPages.Count)
  {
    PSSR.ImportPageNumberOutOfRange(pdfForm.PageNumber, 
                                    importPages.Count,
                                    form._path);
  }
  PdfPage importPage = importPages[pdfForm.PageNumber - 1];
  ....
}

V3010 The return value of function 'ImportPageNumberOutOfRange' is required to be utilized. PdfFormXObject.cs 99

Здесь возвращаемое значение метода ImportPageNumberOutOfRange не используется. Давайте взглянем на него:

public static string ImportPageNumberOutOfRange(....)
{
  return String.Format("The page cannot be imported from document '{2}'," +
    " because the page number is out of range. " +
    "The specified page number is {0}," +
    " but it must be in the range from 1 to {1}.", ....);
}

Видно, что метод возвращает сообщение об ошибке, которое никак не используется. Подобная оплошность может стать причиной затруднённого поиска причины неправильной работы программы. Скорее всего, при значениях pdfForm.PageNumber < 1 или pdfForm.PageNumber > importPages.Count выполнение кода не должно было идти дальше.

Заключение

Резюмируя, можно сказать, что разрабатывать игры становится всё труднее и дороже. Поэтому разработчикам стоит использовать различные инструменты, которые помогут повысить качество кода и удешевить процесс поиска ошибок. Статический анализатор PVS-Studio может стать вашим верным товарищем при создании новой игры.

Мне было бы интересно узнать ваше мнение по данной теме. Быть может, вы являетесь разработчиком игры и уже используете статический анализ? В общем, приглашаю в комментарии для обсуждений.

Кстати, если у вас есть проекты на Unity, которые вы хотите, чтобы мы проверили, то для подобного у нас имеется страница на GitHub.

Вы также можете попробовать PVS-Studio на своём проекте. Возможно, это поможет обнаружить проблемы, которые укрылись от вашего взора во время ревью и тестирования.

Популярные статьи по теме
Повторная проверка Unity статическим анализатором PVS-Studio

Дата: 08 Апр 2022

Автор: Артём Ровенский

Unity – один из самых популярных игровых движков. С его помощью создаётся множество отличных межплатформенных проектов. С нашей последней проверки его исходного кода прошло почти 4 года. Пришло время…
Проверка Barotrauma статическим анализатором PVS-Studio

Дата: 31 Мар 2022

Автор: Михаил Евтихевич

Barotrauma – игра, в которой можно поуправлять подлодкой, попрятаться от монстров и даже поиграть на аккордеоне в попытке не пойти ко дну. Посмотрим, как проект, начатый инди-студией Undertow Games и…
Игра с null: проверка MonoGame статическим анализатором PVS-Studio

Дата: 04 Фев 2022

Автор: Вадим Кулешов

Анализатор PVS-Studio уже не раз был использован для анализа кода библиотек, фреймворков и движков для разработки игр. Пришло время добавить к их списку MonoGame – низкоуровневый gamedev-фреймворк, н…
Nintendo Switch: Drop Test исходников эмулятора Ryujinx

Дата: 30 Июн 2021

Автор: Данила Карпов

Такие компании, как Sony, Microsoft и Nintendo, каждое поколение радуют своих потребителей новыми консолями и различными играми на них. Но вот беда, часть игр является эксклюзивами своих платформ, а …
Анализ Unity проектов: The solution file has two projects named "UnityEngine.UI"

Дата: 09 Июн 2021

Автор: Сергей Васильев

При анализе Unity проекта с помощью PVS-Studio может возникнуть ошибка следующего вида: Error was encountered while trying to open solution file '...': The solution file has two projects named "Unity…

Комментарии (0)

Следующие комментарии
Этот сайт использует куки и другие технологии, чтобы предоставить вам более персонализированный опыт. Продолжая просмотр страниц нашего веб-сайта, вы принимаете условия использования этих файлов. Если вы не хотите, чтобы ваши данные обрабатывались, пожалуйста, покиньте данный сайт. Подробнее →
Принять