понедельник, 11 апреля 2016 г.

Портируем игры Unity 3D для Linux

Инструкция по портированию игр Unity 3D c OS X на Linux. Разбираемся...




Внимание: В статье указаны программы для KDE и Arch-based систем. Для своего дистрибутива и окружения существуют аналоги, ищите сами.


Я хотя и не игроман, но иногда люблю иной раз поиграть в какую-нибудь аркадку и отвлечься. В последнее время игры выходят просто пачками, причем и на Linux тоже. Благодаря кросплатформенным движкам и технологиям, для разработчика не состовляет особого труда выпустить игру для Windows, OS X, Linux, Android и т.д. И одним из таких движков является Unity 3D.
Начиная с версии 4.0 добавлена полноценная поддержка Linux и теперь любой разработчик может выпустить Unity-игру для Linux, но не все так делают. Вы наверное сами замечали в Steam или другом ресурсе, что разработчик отказывается выпускать игру для Linux, ссылаясь на малую рентабельность такого занятия, малое количество пользователей или нагло врет про технические проблемы. В общем отмазок можно придумать множество.
И так, не будем лить воды а перейдем к действию. Для начала я вам расскажу про парочку основных принципов, а потом мы уже перейдем к практике.

Из чего и как устроена игра на Unity?
  • Game/Game.x86_64 (Game.x86) - Плеер Unity 3D
  • Game/Game_Data (или Data) - в корне хранятся все игровые данные (level* , *.assets)
  • Game/Game_Data/Plugins - плагины для правильной работы игры.
  • Game/Game_Data/Resources - каталог ресурсов, иконок для игры.
  • Game/Game_Data/Mono - библиотеки Mono
Почему портируем с OS X а не c Windows?
Да, под Windows больше игр, но начиная с 5-ой версии плеера появились проблемы с шейдерами - розовые артефакты или розовый экран. Все дело в том, что сборка игры для Windows поддерживается только шейдерами DirectX. А OS X, Linux и Android - GLSL. Но вы можете успешно портировать игру 4-ой версии плеера с Windows, если у вас не возникнет проблем с плагинами.

Возможно ли портировать с Android?
Мне это не удавалось, потому как игра скомпилированна для мобильных процессоров и не подходит для десктопов.

Все ли игры можно портировать?
Большинство. Но иногда существуют проблемы в виде отсутствия нужного плагина под Linux-платформу.

Как узнать какие плагины нужны?
Плагины расположены в директории Data/Plugins.

Какие инструменты необходимы для портирования?
  • okteta - HEX-редактор для просмотра версии Unity в игре
  • dmg2img - программа для конвертирования образов dmg в img
  • hfsprogs - утилиты для работы с файловой системой HFS/HFS+
  • mount - программа для монтирования образов
  • libicns - утилита для конвертирования иконок из icns в png
  • wine - нужен для получения Unity-плеера (если кто найдет способ для выдергивания плеера из dmg, то будет очень здорово)
В чем суть портирования?
  • Нужно подложить Linux-версию плеера Unity в игру от OS X
  • Добавить необходимые плагины
  • Добавить библиотеки Mono
  • Переместить и создать нужные директории
  • Возможны разного рода костыли
Где брать Unity Player?
Поехали :)
Устанавливаем необходимые программы:
sudo pacman -S okteta hfsprogs wine
yaourt -S libicns dmg2img
sudo modprobe hfsplus
Для примера я взял сервис itch.io, в котором представлены бесплатные игры. Еще вы можете найти кучу игр с сайта gamejolt.com.
Скачав игру-клон Tappy Plane я увидел, что игра запакована в обычный zip-архив. Но если вам достанется dmg, то вы легко его можете сконвертировать в img и смонтировать в нужную директорию. Открываем директорию с образом dmg и выполняем:
#Создаем каталог game
mkdir game
#Конвертируем образ dmg в img
dmg2img ОБРАЗ.dmg ОБРАЗ.img
#Монтируем образ img в каталог game
sudo mount -o loop -t hfsplus ОБРАЗ.img game


Игру мы распаковали, теперь узнаем версию плеера. Находим в папке игры любой файл *.assets и открываем в Okteta.


Ага, тут у нас Unity 3D 5.3.4f1. Буква f - Final, p - это Patch. В моем случае нужна финальная версия плеера 5.3.4f1, которую мы и будем скачивать. Откуда качать я уже указал выше.
КСТАТИ: Можно нагуглить DEB-версию плеера, чтоб не мучить wine. Достаточно вбить в поиске "Unity 5.3.4f1 deb" и вы найдете на форуме Unity ссылку:
Скачав DEB-пакет, распаковываем его и вытаскиваем Linux-плеер. Обычно он хранится в директориях opt/Unity/Editor/Data/PlaybackEngines/LinuxStandaloneSupport/Variations. Нам нужно 2 каталога:
  • linux32_withgfx_nondevelopment_mono
  • linux64_withgfx_nondevelopment_mono


Копируем их рядом с нашим dmg или zip-архивом игры.
Теперь вернемся к директориям самого распакованного содержимого dmg. В OS X небольшая путаница с каталогами, а потому нужно понять куда переносить какую папку. Для удобства я приведу вам сравнение в виде дерева директорий, что бы было наглядней.
OS X:
├── tappyplane.app
│   └── Contents
│       ├── Data
│       │   └── Managed
│       │       └── etc
│       │           └── mono
│       │               ├── 1.0
│       │               │   ├── DefaultWsdlHelpGenerator.aspx
│       │               │   └── machine.config
│       │               ├── 2.0
│       │               │   ├── Browsers
│       │               │   │   └── Compat.browser
│       │               │   ├── DefaultWsdlHelpGenerator.aspx
│       │               │   ├── machine.config
│       │               │   ├── settings.map
│       │               │   └── web.config
│       │               ├── browscap.ini
│       │               ├── config
│       │               └── mconfig
│       │                   └── config.xml
│       ├── Frameworks
│       │   └── MonoEmbedRuntime
│       │       └── osx
│       │           ├── libmono.0.dylib
│       │           └── libMonoPosixHelper.dylib
│       ├── Info.plist
│       ├── MacOS
│       │   └── tappyplane
│       └── Resources
│           ├── Ageia.tif
│           ├── Data
│           │   ├── globalgamemanagers
│           │   ├── globalgamemanagers.assets
│           │   ├── level0
│           │   ├── level0.resS
│           │   ├── level1
│           │   ├── level1.resS
│           │   ├── Managed
│           │   │   ├── Assembly-CSharp.dll
│           │   │   ├── Mono.Security.dll
│           │   │   ├── mscorlib.dll
│           │   │   ├── System.Core.dll
│           │   │   ├── System.dll
│           │   │   ├── UnityEngine.dll
│           │   │   ├── UnityEngine.dll.mdb
│           │   │   ├── UnityEngine.Networking.dll
│           │   │   └── UnityEngine.UI.dll
│           │   ├── Resources
│           │   │   └── unity_builtin_extra
│           │   ├── resources.assets
│           │   ├── resources.assets.resS
│           │   ├── resources.resource
│           │   ├── sharedassets0.assets
│           │   ├── sharedassets0.assets.resS
│           │   ├── sharedassets1.assets
│           │   └── sharedassets1.assets.resS
│           ├── KeyConfig.nib
│           │   ├── classes.nib
│           │   ├── info.nib
│           │   └── keyedobjects.nib
│           ├── MainMenu.nib
│           │   ├── classes.nib
│           │   ├── info.nib
│           │   └── keyedobjects.nib
│           ├── Mono.tif
│           ├── ScreenSelector.nib
│           │   ├── classes.nib
│           │   ├── info.nib
│           │   └── keyedobjects.nib
│           ├── unity default resources
│           └── UnityPlayerIcon.png

Linux:
├── TapyPlane
│   ├── TapyPlane_Data
│   │   ├── globalgamemanagers
│   │   ├── globalgamemanagers.assets
│   │   ├── level0
│   │   ├── level0.resS
│   │   ├── level1
│   │   ├── level1.resS
│   │   ├── Managed
│   │   │   ├── Assembly-CSharp.dll
│   │   │   ├── Mono.Security.dll
│   │   │   ├── mscorlib.dll
│   │   │   ├── System.Core.dll
│   │   │   ├── System.dll
│   │   │   ├── UnityEngine.dll
│   │   │   ├── UnityEngine.dll.mdb
│   │   │   ├── UnityEngine.Networking.dll
│   │   │   └── UnityEngine.UI.dll
│   │   ├── Mono
│   │   │   ├── etc
│   │   │   │   └── mono
│   │   │   │       ├── 1.0
│   │   │   │       │   ├── DefaultWsdlHelpGenerator.aspx
│   │   │   │       │   └── machine.config
│   │   │   │       ├── 2.0
│   │   │   │       │   ├── Browsers
│   │   │   │       │   │   └── Compat.browser
│   │   │   │       │   ├── DefaultWsdlHelpGenerator.aspx
│   │   │   │       │   ├── machine.config
│   │   │   │       │   ├── settings.map
│   │   │   │       │   └── web.config
│   │   │   │       ├── browscap.ini
│   │   │   │       ├── config
│   │   │   │       └── mconfig
│   │   │   │           └── config.xml
│   │   │   ├── x86
│   │   │   │   └── libmono.so
│   │   │   └── x86_64
│   │   │       └── libmono.so
│   │   ├── Plugins
│   │   │   ├── x86
│   │   │   │   └── ScreenSelector.so
│   │   │   └── x86_64
│   │   │       └── ScreenSelector.so
│   │   ├── Resources
│   │   │   ├── unity_builtin_extra
│   │   │   ├── unity default resources
│   │   │   └── UnityPlayer.png
│   │   ├── resources.assets
│   │   ├── resources.assets.resS
│   │   ├── resources.resource
│   │   ├── sharedassets0.assets
│   │   ├── sharedassets0.assets.resS
│   │   ├── sharedassets1.assets
│   │   └── sharedassets1.assets.resS
│   ├── TapyPlane.x86
│   └── TapyPlane.x86_64

Видите, что в OS X tappyplane.app/Contents/Data хранится каталог Managed, в  котором далее следует Mono. Это не каталог с игровыми данными, потому как отсутствуют файлы *.assets. А каталог Data (с игровыми данными) у нас вообще оказывается здесь tappyplane.app/Contents/Resources/Data. Да, по началу это кажется странным и очень запутанным, но портировав пару игр вы разберетесь, я уверен.
Пока вы ломаете мозг, я продолжу :)
Удаляем лишние файлы и каталоги в директории tappyplane.app/Contents/Resources, кроме каталога Data и файлов unity default resources и UnityPlayerIcon.png.


Переименовываем файл UnityPlayerIcon.png в UnityPlayer.png, вырезаем эти два файла и перемещаем их в tappyplane.app/Contents/Resources/Data/Resources


Теперь переименовываем каталог tappyplane.app/Contents/Resources в tappyplane.app/Contents/TappyPlane
Всё, TappyPlane - это наша директория игры. Все что идет выше вы можете удалить.


И осталось нам добавить лишь Unity-плеер, плагины и Mono для правильной работы игры. Все это уже есть в комплекте с Unity-Editor, который мы ранее скачали. Открываем ранее скопированный каталог linux64_withgfx_nondevelopment_mono, копируем от туда файл LinuxPlayer в нашу папку с игрой под именем TappyPlane/TappyPlane.x86_64.
И из папки linux64_withgfx_nondevelopment_mono/Data копируем папки Mono  и Plugins в TappyPlane/Data
Повторяем процедуру с x86-версией плеера.
Переименовываем TappyPlane/Data в TappyPlane/TappyPlane_Data, делаем файлы TappyPlane.x86_64 и TappyPlane.x86 исполняемыми и пускаем игру.
Вуаля, работает!


В данной игре отсутствуют иконки icns, а потому я просто переименовал обыное лого Unity. Но если вам попадутся иконки, вы можете их сконвертировать в png и положить в ИГРА/ИГРА_Data/Resources/UnityPlayer.png:
icns2png -x ИКОНКА.icns
Вот так занимательно и интересно можно портировать игры в Linux.
Архив с игрой для OS X, портированной для Linux и Unity Player 5.3.4f1.
Удачи :)

3 комментария:

  1. Процесс установки плеера сам по себе тот еще квест ;)

    ОтветитьУдалить
  2. При этом до сих пор не возможно играть в онлайн игры требующие unity3d web player.

    ОтветитьУдалить
  3. Этот комментарий был удален автором.

    ОтветитьУдалить

Примечание. Отправлять комментарии могут только участники этого блога.