Для просмотра видеоинструкции нажмите здесь
Если вы инди-разработчик или небольшая студия, локализация - это то, что вы, скорее всего, не собираетесь реализовывать в первоначальном выпуске своей игры. Тем не менее, для увеличения вашей аудитории и привлечения новых игроков наличие многоязычной поддержки является важным элементом, который вы рассмотрите в следующих версиях. В этом уроке я покажу очень простой способ выполнить локализацию вашей игры без каких-либо сторонних ресурсов.
Предварительные требования
Я собираюсь использовать Unity 2019.3, но подойдут и более ранние версии. Я использовал эту механику в одной из своих игр - Zen Jigsaw - вы можете увидеть ее там в действии.
Как всегда, исходный код доступен на GitHub, пожалуйста, найдите ссылку в конце этой статьи.
Подход, описанный в этом руководстве, лучше всего подходит для игр малого и среднего размера. Требуются два компонента: файлы свойств, которые содержат все игровые тексты, и преобразователь языка для заполнения необходимого текста.
В этом руководстве будут использоваться два языка - английский и русский, но этот подход легко расширяется на все другие поддерживаемые языки.
До Unity у меня был опыт работы с другим популярным фреймворком для разработки игр под названием Libgdx. Если вы когда-либо работали с ним, вы можете найти определенные сходства в описанной здесь технике. Локализация в Libgdx поддерживается "из коробки" и реализуется чрезвычайно просто. Я был немного удивлен, что в Unity до сих пор нет этой обязательной функции. Да, доступен пакет 0.4, но он все еще находится на ранней стадии разработки.
Часть 1. Создание файлов свойств
Чтобы получить доступ к файлам свойств из кода, мы сохраним их в папке «Ресурсы».
Я называю эти файлы «свойствами» из-за структуры, например, файл English.txt имеет следующее содержимое:
welcome=Welcome! long_text=This is a\nvery long\ntext
Каждый файл свойств будет соответствовать условиям контракта:
- Отдельная строка состоит из двух частей - клавиши слева от разделителя и значения справа.
- Строки разделяются новой строкой
- Имя файла соответствует Unity
SystemLanguage
enum - Все файлы свойств имеют одинаковые ключи, но разные локализованные значения.
- Разделитель между ключом и значением - «=», вы также можете использовать любой другой символ.
Часть 2. Чтение файлов свойств
Чтобы использовать подготовленные ранее файлы, давайте создадим скрипт, который будет отвечать за чтение файлов построчно, собирая все пары ключ-значение и заполняя их в текстовые компоненты:
public class LangResolver : MonoBehaviour { private const char Separator = '='; private readonly Dictionary<string, string> _lang = new Dictionary<string, string>(); private SystemLanguage _language; private void Awake() { DontDestroyOnLoad(gameObject); ReadProperties(); Debug.Log(_lang.Count); Debug.Log(_lang.Keys.First()); Debug.Log(_lang.Values.First()); } private void ReadProperties() { _language = Application.systemLanguage; var file = Resources.Load<TextAsset>(_language.ToString()); if (file == null) { file = Resources.Load<TextAsset>(SystemLanguage.English.ToString()); _language = SystemLanguage.English; } foreach (var line in file.text.Split('\n')) { var prop = line.Split(Separator); _lang[prop[0]] = prop[1]; } } }
Давайте создадим новый пустой игровой объект и присоединим к нему LangResolver.
Если вы сейчас нажмете кнопку Play, вы увидите следующий результат:
Это размер _lang
dictionary, а также первый ключ и значение из файла свойств на английском языке!
Важно иметь значение по умолчанию на случай, если кто-то запустит вашу игру на неподдерживаемом языке. Обычно используется английский, но он может отличаться.
Примечание! Этот сценарий предназначен для инициализации только один раз, в идеале в самой первой сцене (обычно в сцене Splash). Если у вас нет такой сцены, следует добавить проверку на наличие дубликатов.
На этом этапе вам может быть интересно: где на сцене находится селектор языка? Я намеренно исключил эту часть UX за рамки учебника. В современных играх возможность смены языка больше не является необходимостью, полагаться на системный язык совершенно нормально. Но у меня это есть в Расширенном руководстве по локализации, обязательно ознакомьтесь с ним!
Часть 3. Локализация
Следующим шагом является привязка ключей от свойств к текстовым компонентам. Для этого создадим следующий вспомогательный класс:
public class LangText : MonoBehaviour { public string Identifier; }
Этот скрипт будет прикреплен к каждому текстовому компоненту, который мы хотим заполнить текстом из файлов. Поле Идентификатор - это ключ от свойств.
Последний шаг - заполнить все тексты. Давайте добавим в LangResolver следующий общедоступный метод:
public void ResolveTexts() { var allTexts = Resources.FindObjectsOfTypeAll<LangText>(); foreach (var langText in allTexts) { var text = langText.GetComponent<Text>(); text.text = Regex.Unescape(_lang[langText.Identifier]); } }
Примечание! Regex.Unescape
метод используется для правильного анализа новых строк и других возможных символов форматирования из файлов свойств.
Хотя вы можете вызвать этот метод из самого скрипта (например, из Awake), я предпочитаю иметь специальный UIResolver
class:
public class UIResolver : MonoBehaviour { private void Start() { FindObjectOfType<LangResolver>().ResolveTexts(); } }
Часть 4. Тестирование
Теперь сложнее всего протестировать его на разных языках, так как вам нужно будет настроить язык вашей ОС. Я считаю, что вы не хотите этого делать, поэтому давайте просто «смоделируем» это поведение, изменив первую строку в ReadProperties
method на _language = SystemLanguage.Russian
Если вы нажмете кнопку Play, вы увидите:
Не волнуйтесь, если вы не умеете читать кириллицу, текст - это прямой перевод.
С английским языком по умолчанию результат будет следующим:
В общем, вам не нужно хранить какой-либо текст в самом текстовом компоненте, поскольку его текст в любом случае будет заменен. Однако может быть полезно понять, как текст будет выглядеть с точки зрения UX, поэтому я бы предложил сохранить некоторый текст в редакторе Unity, используя файлы свойств как окончательный источник истины.
Потом
Молодцы, закончили урок! Если у вас есть какие-либо вопросы, оставьте их в разделе комментариев ниже.
Исходные файлы проекта можно найти в этом репозитории GitHub.
Игру, о которой я говорил, можно скачать здесь Zen Jigsaw.