Save the Penguin — опыт разработки Android-игры на Unity | OTUS
🔥 Начинаем BLACK FRIDAY!
Максимальная скидка -25% на всё. Успейте начать обучение по самой выгодной цене.
Выбрать курс

Курсы

Программирование
iOS Developer. Basic
-25%
Python Developer. Professional
-25%
Разработчик на Spring Framework
-25%
Golang Developer. Professional
-25%
Python Developer. Basic
-25%
iOS Developer. Professional
-25%
Node.js Developer
-25%
Unity Game Developer. Professional
-25%
React.js Developer
-25%
Android Developer. Professional
-25%
Software Architect
-25%
C++ Developer. Professional
-25%
Backend-разработчик на PHP Web-разработчик на Python Алгоритмы и структуры данных Framework Laravel PostgreSQL Team Lead Разработчик голосовых ассистентов и чат-ботов Архитектура и шаблоны проектирования Agile Project Manager Нереляционные базы данных Супер - интенсив по паттернам проектирования Супер-практикум по использованию и настройке GIT IoT-разработчик Подготовка к сертификации Oracle Java Programmer (OCAJP) Супер-интенсив «СУБД в высоконагруженных системах» Супер-интенсив "Azure для разработчиков"
Инфраструктура
Мониторинг и логирование: Zabbix, Prometheus, ELK
-25%
DevOps практики и инструменты
-25%
Архитектор сетей
-25%
Инфраструктурная платформа на основе Kubernetes
-25%
Супер-интенсив «ELK»
-16%
Супер-интенсив «IaC Ansible»
-16%
Administrator Linux. Professional MS SQL Server Developer Безопасность Linux PostgreSQL Reverse-Engineering. Professional CI/CD VOIP инженер Супер-практикум по работе с протоколом BGP Супер - интенсив по паттернам проектирования Супер - интенсив по Kubernetes Administrator Linux.Basic Супер-интенсив "Tarantool"
Специализации Курсы в разработке Подготовительные курсы
+7 499 938-92-02

Save the Penguin — опыт разработки Android-игры на Unity

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

Идея для первой игры возникла быстро — было принято решение создать таймкиллер в портретной ориентации, причём таким образом, чтобы можно было играть одним пальцем. Собственно говоря, это разумно, т. к. не стоит выбирать для первой игры слишком сложный проект — велика вероятность, что вы отвлечётесь, потеряете мотивацию и не доведёте дело до конца. В нашем случае главным героем стал пингвин. Почему? Потому что пингвины классные))

24_1-1801-580f75.jpg

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

Вопрос № 1: адаптация под разные разрешения

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

36_1-1801-c280c0.jpg

Вопрос № 2: оптимизация

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

    public class QualityManager : MonoBehaviour
    {
        public string FolderInResources;
        private string _qSuffix;


        void Start()
        {
            _qSuffix = GetQuality();

            ManageQuality();
        }

        private string GetQuality()
        {
            var screenH = Screen.height;

            if (screenH > 2000)
                return "4x";

            if (screenH < 960)
                return "1x";

            return "2x";
        }

        private void ManageQuality()
        {
            if (_qSuffix != "2x")
            {
                var spriteName = GetComponent<SpriteRenderer>().sprite.name.Split('@')[0];

                var sprite = Resources.Load<Sprite>(String.Format("{0}/{1}@{2}", FolderInResources, spriteName, _qSuffix));

                GetComponent<SpriteRenderer>().sprite = sprite;
            }

            Resources.UnloadUnusedAssets();
        }
    }

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

public class ReSkinner : MonoBehaviour
    { 
        public string SkinName;


        void LateUpdate()
        {
            var subSprites = Resources.LoadAll<Sprite>(SkinName);

            foreach (var render in GetComponentsInChildren<SpriteRenderer>())
            {
                var newSprite = Array.Find(subSprites, item => item.name == render.sprite.name);

                if (newSprite)
                {
                    render.sprite = newSprite;
                }
            }
        }
    }

Следующий момент — при разработке нередко применяли метод GetComponent в Update. На самом деле, делать это не рекомендуется, ведь GetComponent считается ресурсозатратной операцией. В принципе, во многих случаях эту операцию лучше вынести в метод Start, что и было сделано.

Итог всех вышеописанных танцев с бубном — увеличение производительности.

Вопрос № 3: сохранение данных

В Unity есть несколько способов для сохранения данных. Самый простой, по которому пошли разработчики, — хранение данных посредством встроенного класса PlayerPrefs. В этом случае хранимые данные не должны быть более 1 МБ, чего в целом было достаточно для решения поставленных задач. Но нужно ведь и хранить информацию о скинах, точнее, о том, доступен ли тот либо иной скин пользователю. По большому счету, речь идёт о булевой переменной, а хранить несколько десятков таких переменных довольно затратно. Решение — применение битовых масок.

static class FlagCollection
    {
        public static int SetFlag(this int collection, int numberFlag, bool valueFlag)
        {
            if (numberFlag < 0 || numberFlag >= 32)
            {
                throw new ArgumentException("Number of flag isn't correct");
            }

            if (valueFlag)
            {
                return collection | (1 << numberFlag);
            }
            else
            {
                return collection & ~(1 << numberFlag);
            }
        }

        public static bool GetFlag(this int collection, int numberFlag)
        {
            if (numberFlag < 0 || numberFlag >= 32)
            {
                throw new ArgumentException("Number of flag isn't correct");
            }

            return (collection & (1 << numberFlag)) != 0;
        }
    }

Выводы

Если вы хотите сделать свою игру, но что-то вас останавливает — отбросьте все сомнения и действуйте! Главное заключается в том, что вы получите бесценный опыт. И помните, что успех складывается из мелочей, поэтому будьте внимательны к деталям. Старайтесь делать всё качественно, ведь плохо реализованный продукт является заведомо провальным.

45_1-1801-8395ed.jpg

Вот и всё, итоговый результат можете посмотреть по этому адресу: https://www.apkmonk.com/app/com.pacetap.savethepenguin/.

Не пропустите новые полезные статьи!

Спасибо за подписку!

Мы отправили вам письмо для подтверждения вашего email.
С уважением, OTUS!

Автор
0 комментариев
Для комментирования необходимо авторизоваться
🎁 Максимальная скидка!
Черная пятница уже в OTUS! Скидка -25% на всё!