как на unity сделать приложение
Краткое руководство. Создание приложения Android в Unity с помощью Пространственных привязок Azure
В этом кратком руководстве показано, как создать приложения Android в Unity с помощью Пространственных привязок Azure. «Пространственные привязки Azure» — это кроссплатформенная служба разработчика, которая позволяет создавать среды смешанной реальности с применением объектов, не меняющих своего расположения на устройствах с течением времени. После завершения вы получите приложение Android ARCore, разработанное с использованием Unity, которое может сохранять и отзывать пространственные привязки.
Если у вас еще нет подписки Azure, создайте бесплатную учетную запись Azure, прежде чем начать работу.
Предварительные требования
В рамках этого краткого руководства вам потребуются:
Создание ресурса Пространственных привязок
В области слева выберите Создать ресурс.
Выполните поиск по запросу Пространственные привязки с помощью поля поиска.
Выберите Пространственные привязки, а затем щелкните Создать.
В области Учетная запись Пространственных привязок выполните следующие действия.
Введите уникальное имя ресурса, используя обычные буквенно-цифровые символы.
Выберите подписку, к которой нужно присоединить ресурс.
Создайте группу ресурсов, нажав Создать. Назовите ее myResourceGroup и нажмите ОК.
Группа ресурсов — это логический контейнер, в котором происходит развертывание ресурсов Azure (например, веб-приложений, баз данных и учетных записей хранения) и управление ими. Например, в дальнейшем можно удалить всю группу ресурсов при помощи одного простого действия.
Выберите расположение (регион), в котором будет размещен ресурс.
Выберите Создать, чтобы начать создание ресурса.
После создания ресурса на портале Azure отобразится оповещение о завершении развертывания.
Выберите Перейти к ресурсу. Теперь можно просмотреть свойства ресурса.
Скопируйте значение идентификатора учетной записи ресурса в текстовый редактор для дальнейшего использования.
Скопируйте также значение домена учетной записи ресурса в текстовый редактор для дальнейшего использования.
В разделе Параметры выберите элемент Ключ доступа. Скопируйте значение первичного ключа (ключа учетной записи) в текстовый редактор для дальнейшего использования.
Чтобы подготовить среду для Azure CLI, выполните указанные ниже действия.
Используйте среду Bash в Azure Cloud Shell.
При необходимости установите Azure CLI, чтобы выполнять справочные команды CLI.
Если вы используете локальную установку, выполните вход в Azure CLI с помощью команды az login. Чтобы выполнить аутентификацию, следуйте инструкциям в окне терминала. Сведения о дополнительных возможностях, доступных при входе, см. в статье Вход с помощью Azure CLI.
Если появится запрос, установите расширения Azure CLI при первом использовании. Дополнительные сведения о расширениях см. в статье Использование расширений с Azure CLI.
Выполните команду az version, чтобы узнать установленную версию и зависимые библиотеки. Чтобы обновиться до последней версии, выполните команду az upgrade.
После входа выполните команду az account set, чтобы выбрать подписку, в которой нужно задать учетную запись пространственных привязок:
Выполните команду az group create, чтобы создать группу ресурсов, или примените существующую группу ресурсов:
Группа ресурсов — это логический контейнер, в котором происходит развертывание ресурсов Azure (например, веб-приложений, баз данных и учетных записей хранения) и управление ими. Например, в дальнейшем можно удалить всю группу ресурсов при помощи одного простого действия.
Вы можете просмотреть текущие учетные записи пространственных привязок для группы ресурсов с помощью команды az spatial-anchors-account list:
Вы также можете просмотреть учетные записи пространственных привязок для своей подписки:
Выполните команду az spatial-anchors-account create, чтобы создать учетную запись пространственных привязок:
Просмотрите свойства ресурса с помощью команды az spatial-anchors-account show:
Скопируйте значение идентификатора учетной записи для ресурса и значение домена учетной записи для ресурса в текстовый редактор (они понадобятся позже).
Выполните команду az spatial-anchors-account key show, чтобы получить первичный и вторичный ключи:
Скопируйте значения ключей в текстовый редактор (они понадобятся позже).
Если необходимо повторно создать ключи, выполните команду az spatial-anchors-account key renew:
Вы можете удалить учетную запись с помощью команды az spatial-anchors-account delete:
Сначала подготовьте среду для Azure PowerShell:
После входа воспользуйтесь командлетом Set-AzContext, чтобы выбрать подписку, в которой нужно задать учетную запись пространственных привязок:
Выполните командлет New-AzResourceGroup, чтобы создать группу ресурсов, или воспользуйтесь существующей группой ресурсов:
Группа ресурсов — это логический контейнер, в котором происходит развертывание ресурсов Azure (например, веб-приложений, баз данных и учетных записей хранения) и управление ими. Например, в дальнейшем можно удалить всю группу ресурсов при помощи одного простого действия.
Вы можете просмотреть текущие учетные записи пространственных привязок для группы ресурсов с помощью командлета Get-AzSpatialAnchorsAccount:
Вы также можете просмотреть учетные записи пространственных привязок для своей подписки:
Запустите командлет New-AzSpatialAnchorsAccount, чтобы создать собственную учетную запись пространственных привязок:
Просмотрите свойства ресурса с помощью командлета Get-AzSpatialAnchorsAccount:
Скопируйте значение accountId свойства и значение accountDomain свойства в текстовый редактор (они понадобятся позже).
Выполните командлет Get-AzSpatialAnchorsAccountKey, чтобы получить первичный и вторичный ключи.
Скопируйте значения ключей в текстовый редактор (они понадобятся позже).
Если необходимо повторно создать ключи, используйте командлет New-AzSpatialAnchorsAccountKey:
Удалить учетную запись можно с помощью командлета Remove-AzSpatialAnchorsAccount:
Скачивание и открытие примера проекта Unity
Клонируйте репозиторий примеров, выполнив следующие команды:
Следуйте приведенным здесь инструкциям, чтобы скачать и импортировать пакеты SDK для ASA, необходимые для платформы Android.
В Unity откройте проект в папке Unity. Unity может уведомить вас о разнице между версией в проекте и версией, установленной на компьютере. Это предупреждение допустимо, если версия Unity Editor новее, чем та, с помощью которой создан проект. В таком случае выберите Continue (Продолжить). Если ваша версия старше, чем требуется проекту, щелкните Quit (Выйти) и обновите Unity Editor.
Откройте Build Settings (Параметры сборки), выбрав пункты File > Build Settings (Файл > Параметры сборки).
В разделе Platform (Платформа) выберите Android и нажмите Switch Platform (Сменить платформу), чтобы перейти на платформу Android. Если отсутствуют какие-то дополнительные компоненты Android, Unity может запросить их установку.
Закройте окно Build Settings (Параметры сборки).
Настройка сведений об учетной записи
Следующим шагом является настройка приложения для использования данных вашей учетной записи. Вы скопировали значения ключа учетной записи, идентификатора учетной записи и домена учетной записи в текстовый редактор, как указано ранее в разделе Создание ресурса Пространственных привязок.
Выберите SpatialAnchorConfig. В области Инспектор введите Account Key в качестве значения ключа учетной записи Пространственных привязок, Account ID в качестве значения идентификатора учетной записи Пространственных привязок и Account Domain в качестве значения домена учетной записи Пространственных привязок.
Экспорт проекта Android Studio
Откройте Build Settings (Параметры сборки), выбрав пункты File > Build Settings (Файл > Параметры сборки).
В разделе Scenes In Build (Сцены в сборке) убедитесь, что возле всех сцен установлен флажок.
Следуйте инструкциям в программе для размещения и отзыва привязки.
Устранение неполадок
Проблемы отрисовки
Очистка ресурсов
На предыдущем шаге вы создали ресурсы Azure в группе ресурсов. Если вы считаете, что в будущем эти ресурсы вам не понадобятся, их можно удалить, удалив группу ресурсов.
В меню или на странице Главная портала Azure выберите Группы ресурсов. Затем на странице Группы ресурсов выберите myResourceGroup.
На странице myResourceGroup убедитесь, что перечислены те ресурсы, которые нужно удалить.
Выберите Удалить группу ресурсов, введите myResourceGroup в текстовое поле для подтверждения и щелкните Удалить.
Дальнейшие действия
В этом кратком руководстве вы создали учетную запись Пространственных привязок. Затем вы настроили и развернули приложение для сохранения и повторного вызова пространственных привязок. Дополнительные сведения о том, как улучшить приложение таким образом, чтобы оно совместно использовало пространственные привязки с другими устройствами, см. в следующем руководстве.
Моя история создания мотивационного приложения (iOS и Android) для дочери с дочерью на Unity и C#
Это первая часть истории (вперемешку с рассказом о моих ошибках и их решениях) о том, как я (где-то два года в свободное время) разрабатывал мобильное приложение под iOS и Android, которое бы мотивировало мою дочь решать примеры по математике, чтобы она достигла автоматизма в основах арифметики (склад числа 10 или табличка умножения). В итоге, получилось приложение, позволяющее ребёнку зарабатывать деньги своим умом.
Использовал я движок Unity и язык C#, а также дополнительный набор софта вроде обязательного Photohsop или Audacity (для создания звуков).
План рассказа (часть первая)
Предыстория и колорадские жуки
Мой предыдущий опыт — это несколько лет в 3D и, с недавних пор, разработка нескольких инди-игр на пару с программистом, где я выступал в основном только в роли дизайнера и художника (очень редко пописывая какие-то элементарные скрипты на C#). Хотя, с программированием знаком не понаслышке (колупал Basic в школе и баловался с C/C++ в универе).
Вся эта эпопея началось с проблемы. Я увидел, что при решении школьных задач, дочь «буксует» и ошибается не на чём-то сложном, а на основах. Я решил, что будет прикольно, если я напишу ей забавное приложение, где она в игровой форме будет решать примеры (набираясь таким образом опыта и достигая автоматизма). И, чтобы мотивировать её ещё больше, я сделал так, что за правильное решение примеров она получала деньги (количество денег подсчитывало приложение на основе количества правильных ответов, а я потом выводил нужную сумму, выплачивая дочери наличные).
Хотя… эта история началась ещё раньше. Сначала я сделал дочери приложение, которое выплачивало деньги за то, что она учила английские слова. Но это приложение оказалось намного сложнее реализовать так, чтобы оно стало удобным не только для меня (разработчика) и моей дочери, но также и для других родителей. Поэтому, английское приложение пока так и остаётся внутренней разработкой.
Я выбрал деньги в качестве мотиватора, поскольку это было проще всего реализовать. А ещё из-за личных воспоминаний из детства: я обожал делать всё за деньги. Даже если это была очень нудная работа, типа собирать колорадских жуков с картошки. Помню, насобирал их полулитровую банку (родители мне платили 1 копейку за каждого жука). Вот я и подумал, что раз дочь моя (я это не проверял, но крепко уверен в этом), то и ей это должно понравиться. Ну и в итоге не прогадал.
Моя жена против того, чтобы стимулировать детей делать что-то за деньги. Но мой аргумент её разубедил немножко: в случае этого приложения, ребёнок получает деньги не за то, что он и так должен делать (типа домашнее задание), а за то, что он дополнительно практикует математику в своё свободное время.
Вторая причина, почему я взялся за разработку — я хотел попрактиковаться в программировании. «Стать программистом» было моей заветной мечтой ещё с первых классов школы (сразу после мечты «стать учёным», но перед мечтой «делать мультики»).
Монетизация и удовольствие
Изначально я делал это приложение (рабочее название было Math4Ami) исключительно под iPod touch 5 дочери. Я даже не думал делать приложение доступным на всех iOS устройствах или публиковать его для всех и, тем более, не думал выпускать его для платформы Android (наслушался страшных историй от iOS разработчиков плюс, мне не на чём тестировать Андроид версию).
Какое-то время назад я загорелся желанием опубликовать его в AppStore (меня очень манила мысль, что у меня будет своё приложение в Apple магазине и все это смогут увидеть).
Подумал, что за месяц управлюсь. Ведь весь функционал был готов, оставалось дело за малым — сделать его рабочим для всех соотношений сторон экрана и понятным не только для меня, но и для других родителей. И вот, спустя полгода, я опубликовал его в AppStore и Google Play.
Я изначально решил сделать Math4Ami полностью бесплатным без намёка на монетизацию. Причин для этого решения несколько.
Первая. Как вы уже поняли, я изначально делал его бесплатным для дочери и не хотел ничего прикручивать в «конце» разработки.
Вторая. Я решил, что это будет разработка для собственного удовольствия. У меня уже есть подобный опыт — я делаю блог для удовольствия (который изначально только кушал средства: деньги на хостинг и на доменное имя, время на написание статей и их продвижение). Моя логика была следующей: если я плачу деньги за посещение аквапарка, покупку книги или мороженного, чтобы получить удовольствие, то почему я не могу себе позволить платить деньги за хостинг, доменное имя или членство в Apple Developer Program, если это тоже приносит мне удовольствие.
Третья — ради более широкой аудитории, которая бы значительно урезалась, сделав я приложение платным (как делают многие разработчики детских приложений). Другие типы монетизации я отмёл по нижеописанным причинам.
Внутриигровую рекламу я на дух не переношу — не люблю когда дизайн приложения уродуют рекламные сообщения (разве что кроме рекламы в виде просмотров видео по желанию, а не когда видео выскакивает из-за угла). К тому же, для участия в программах «Made for kids» у Apple и «Designed for Families» у Google, нужно строго фильтровать показываемую детям рекламу.
Внутриигровые покупки я сам, как родитель, блокирую на всех устройствах и дети, когда качают приложения самостоятельно, просто физически не могут ничего купить внутри приложения. Другое дело, когда родитель сам изначально покупает приложение для ребёнка (но об этом я уже сказал выше).
Почему Unity и как
Выбрал я Unity поскольку работал в нём раньше и мне понравилось. Также у меня был хороший друг программист на C# и я надеялся, что он мне поможет с программированием, если что. А ещё у Unity шикарное сообщество и очень легко найти ответы в Гугле почти на все вопросы реализации чего-то там на C# + Юнити.
С Unreal я тоже работал (как 3D художник), но так и не разобрался ни с C++, ни с 2D функционалом.
Изначально Math4Ami было «облачным», хотя это и громко сказано. Все данные хранились на моём eVPS (Elastic Virtual Private Server) и я использовал FTP, чтобы передавать TXT-файлы с данными и настройками приложения (до использования базы данных руки так и не дошли, хотя первые шаги в написании своего сервера на node.js я предпринял). Для работы с ftp я прикрутил к Unity лёгкий в использовании Simple C# FTP Class.
Потом, когда я решил сделать app публичным, я отказался от серверной части.
С одной стороны, это было бы слишком заморочено: делать аутентификацию (этого пользователи ох как не любят) или сохранять в iCloud идентификатор сессии с помощью NSUbiquitousKeyValueStore (это позволило бы автоматически идентифицировать пользователя между удалением апликухи и повторной установкой), но я так и не разобрался с этим (возможно, мне бы помогла статья Пишем плагин для Unity правильно. Часть 1: iOS, но тогда её ещё не было).
С другой стороны, данные в этом приложении не такие уж и важные, чтобы их нужно было хранить на сервере.
С третьей стороны, не было необходимости в серверной синхронизации. Вот для моего приложения по обучению английскому — там да, синхронизация была нужна. Поскольку родитель добавляет новые слова в родительском приложении, а ребёнок учит их в детском приложении (хотя, может я и любитель всё усложнять).
В итоге я сделал, чтобы всё хранилось локально (на устройстве), но уже не в txt, а JSON формате.
ScriptableObject и правильные ответы
JSON формат в связке с ScriptableObject оказался шикарной находкой. Я использовал родные методы UnityEngine для сериализации объектов в json — JsonUtility (а потом сохранял текстовые файлы json локально на устройстве в папку Application.persistentDataPath).
ScriptableObject (SO) — это отдельная тема разговора, но я всё же её затрону. Даже не представляю, как я раньше жил без SO.
Всё что я использую в работе, я почерпнул из этих двух мегаполезных видео о принципах работы с SO (и сопутствующего кода на GitHub и Bitbucket):
Лично я использовал SO для таких целей:
Единственный минус SO для работы с данными — в нём нельзя хранить данные между сессиями приложения: ассет SO (после холодного запуска приложения) будет всегда содержать данные, которые вы записали туда в редакторе. Поэтому логика работы у меня такова:
Есть (очевидный) недостаток такого подхода — нельзя сохранить на диск только один изменившийся параметр (если их несколько в SO), всё время приходится сохранять текстовый json-файл полностью.
Но многие данные не нужно сохранять на диск (к примеру, текущее количество правильных ответов) и тогда SO является мощным инструментом, позволяющий значительно упростить мне работу.
На видео ниже я показываю пример моей реализации учёта верных и неправильных ответов с помощью UnityEvent (событие — изменилось ли количество правильных ответов) + Listener (слушатели делают какую-то работу, если услышали, что получен правильный ответ, а логика подписки слушателей на событие также реализована на SO) + SO (ведёт учёт количества правильных ответов):
Таким образом, я могу не только руками вводить правильные и ошибочные ответы, но просто двигая ползунок, генерировать новые примеры и тестировать логику работы приложения.
Anima2D, персонажи и дёрганая улыбка
На видео выше видно, что когда падает новая копейка, то другие копейки начинают широко улыбаться, а когда падает какашка, то копейки в ужасе.
Я долго не мог победить глюк, когда при переключении с одного типа улыбки на другую, смена происходила не мгновенно, а моргала (из одного состояния в другое) какое-то время. Дальше я расскажу, как я это реализовал и как победил этот глюк.
Смена выражений лица реализована с помощью скрипта Sprite Mesh Animation, входящего в состав мощного плагина Anima2D (который Unity недавно выкупила и сделала бесплатным). Этот скрипт по сути просто переключает спрайты для рта (улыбка, открытая улыбка, испуганный рот) с помощью ползунка Frame:
Вся засада в том, что значение ползунка Frame нельзя изменять напрямую из скриптов, а только через систему анимации. Поэтому я создал новый анимационный слой OpenSmile (стрелка 1 на рис. ниже) в режиме смешивания Additive с весом Weight=1 и добавил туда анимацию ужаса (Coin_scared) и широкой улыбки (SmillingWide).
Кстати, вы заметили, какой плохой пример я подаю, с именами анимации? Я всё ещё в процессе приведения имён к единому стилю. Правильно было бы изменить Coin_scared на A_CoinScared (почему именно так читайте в разделе «О чём я жалею»).
Я создал новый слой, а не использовал старый, поскольку не хотел перезаписывать анимацию рта. Мне нужно было только менять спрайт рта (с улыбки на широкую улыбку или с улыбки на ужас) и чтобы при этом анимация рта осталась с базового слоя. Именно поэтому я выбрал режим смешивания Additive — добавление новой анимации к уже существующей (не перезаписывая её).
По своей сути, анимации SmillingWide и Coin_scared — это просто анимация ползунка Frame в позицию 1 и 2, соответственно.
Вся проблема была в том, что переход из любого состояния в состояние ужаса (при клике на переход (стрелка 2 на рис. выше), в инспекторе открываются свойства этого перехода (стрелка 3 на рис. выше)) происходил не моментально, а плавно на протяжении отрезка времени Transition Duration (стрелка 4 на рис. выше), которое было не нулевым по умолчанию. Таким образом, значение ползунка Frame не могло изменяться правильно, ведь там были только целые числа, а значит между 0 и 1 нету промежуточного значения. Поэтому, чтобы избавиться от моргающего глюка, нужно было всего лишь обнулить величину Transition Duration.
Ну а условием перехода в состояние ужаса служит trigger isScared (стрелка 5 на рис. выше). Я активирую этот триггер в коде с помощью следующего обращения к объекту, на котором висит компонент Animator (с контролером, слои которого я показал выше):
Как я переводил приложение на разные языки
Где-то здесь же, на Хабре, я читал, что о локализации нужно задумываться ещё в начале создания приложения и я последовал этому совету… сразу же… спустя полтора года разработки (как только решил, что Math4Ami будет публичным).
Почему я выбрал именно Lean Localization (кроме той причины, что плагин бесплатный) я уже не помню, но помню, что выбирал долго и усердно.
Пользоваться им оказалось очень просто. Можно как вручную задавать язык, так и использовать автоматическое определение языка. Я остановился на автоматическом определении языка (по примеру других детских приложений).
Плагин переводит всё (от текста до звуков и картинок).
Но я всё равно допустил одну ошибку с локализацией (хотя я сделал её намеренно, поскольку хотел попробовать разные подходы). Ошибка в том, что я поместил не все фразы в текстовый файл (слева на рис. ниже). Некоторые фразы остались внутри компоненты Lean Localization (справа на рис. ниже). Поэтому теперь, когда я отдаю этот файл переводчику на японский, мне придётся поработать вручную (чтобы перенести ВСЁ в текстовый файл).
Хотя, некоторые вещи нельзя перевести текстовым файлом (типа пробела » «, который я использовал в качестве разделителя между тысячами) — придётся всё равно использовать компоненту.
Сочный iTween
Когда-то давно я посмотрел шикарнющее видео Juice it or lose it о том, как всякие маленькие микродвижения и нюансы анимации помогают из скучной игры сделать захватывающее дух действие. А ещё до этого мне в душу запало другое видео — The art of screenshake, которое на самом деле не только и не столько о дрожании экрана.
Всё время, пока создавал Math4Ami, я держал в уме концепции из вышеприведённых видео, а также ту мысль, что вся эта дополнительная анимация должна быть максимально короткой и действовать больше на подсознание, чем на сознание. Порой, я тратил больше времени на добавление «сочности», чем на добавление полезного функционала.
Только одно место меня смущает очень сильно — финальный подсчёт заработанных денег (вы можете видеть этот момент в конце моей видеодемонстрации выше). Я его укоротил как только мог, но он всё равно занимает чуть больше 4 секунд (исчезает клавиатура, появляется надпись победа, идёт подсчёт копеек, выезд таблицы рекордов, получение шильдика «Новый рекодр», отображение кнопки «Еще»).
Лучшим «источником сока» для меня является бесплатное дополнение iTween. Даже не представляю, как без него вообще можно что-то делать в Unity. Я его использую везде, где нужна хоть какая-то анимация (будь то анимация кнопки или появление пункта меню или анимация подсчёта копеек).
Я пробовал реализовывать что-то подобное самостоятельно на основе корутинов и Mathf.Lerp или Mathf.MoveTowards, но это было не гибко и не универсально (а порой и работало по разному в редакторе и на устройстве). Поэтому сейчас я не стараюсь изобретать велосипед, а просто наслаждаюсь iTween.
Есть и подводные камни у этой системы анимации, с которыми я неправильно боролся поначалу:
К примеру (по последнему пункту), объект А запускает iTween, чтобы он работал на объекте Б. Чтобы остановить iTween анимацию, нельзя просто запустить iTween.Stop() на объекте А. Нужно запустить iTween.Stop(объект Б).
Сильной стороной iTween является возможность использования разных типов изинга (type of easing). Изинг — это параметр, который смягчает движение (чтобы оно не начиналось рывком и не заканчивалось тупо).
Обалденной находкой для меня стали типы изинга:
Чтобы подобрать нужный изинг, я использую наглядную Easing Demo (нужен флеш). А здесь я беру документацию ко всем типам анимации iTween.
Статистика Apple и Google хорошо, но Unity Analytics лучше
Ещё по опыту прошлых игр я знал, что иметь свою собственную статистику — это очень классно. Сначала я хотел создать какую-то свою систему логирования, но потом вспомнил о Unity Analitics. И какое же было моё удивление, когда оказалось, что у бесплатной версии функционал для моего случая ничем не ограничен. Хуже мне пришлось бы, будь у меня какая-то монетизация, тогда инструменты аналитики доступны только для Pro подписчиков.
Просто встраивая Analytics.CustomEvent в нужное место кода, я могу отслеживать какие примеры пользуются большей популярностью, сколько дети решают примеров в первые дни или спустя время и т.д.
Я могу в одном месте сравнивать данные с разных платформ (iOS и Android).
А сколько там всего интересно, что хотелось бы попробовать, да всё руки не доходят. Типа Remote Settings (изменение контента приложения без заливки обновления) или A/B Testing или Tutorial Manager.
Visual Studio наподобие Sublime
В прошлом, когда мне нужно было править какой-то код (будь-то python, html или node.js) я использовал Notepad++ (полностью бесплатный, но только под Windows) и Sublime Text (платный под все ОС, но можно полноценно пробовать бесплатно).
В Unity я сидел на MonoDevelop, но он меня так задолбал своими глюками (типа невозможность переключаться между раскладками или вставить что-то, скопированное за пределами Mono), что я решил — пора бросать тонущий корабль и перелез на Visual Studio Community 2017 (благо, она бесплатная для одиноких, как я, разработчиков).
Для разработчиков на Unity 2018 сейчас это не актуально, так как в составе 2018-ой версии идёт мультиплатформенный Visual Studio Code. Но я хотел, чтобы моё приложение работало под iOS 7 (поскольку iPhone у дочери именно с этой iOS), поэтому нужно было использовать любую версию Unity старее 2018-ой.
Помогло мне с переходом на VS видео How to setup Visual Studio with Unity.
С коробки VS не имеет всех тех классных штук, к которым я привык в других редакторах, поэтому я упростил себе жизнь:
Мои скрипты для этого приложения на GitHub. Там только мои скрипты, а не весь Unity проект — извините, если из-за этого их невозможно будет понять. Я до последнего момента не планировал давать ссылку на исходники, поскольку не считаю мой код таким, на который стоит ориентироваться. Но потом передумал из-за шанса, что более опытные разработчики могут указать на мои ошибки.
Это конец первой части. Продолжение читайте во второй части, где я расскажу:
Ссылки
Список ссылок из тела статьи в очерёдности их упоминания: