- PVSM.RU - https://www.pvsm.ru -

Unity3d + SQLite

Это будет практическое руководство по использованию SQLite в Unity3d. Я расскажу что это такое, для чего может потребоваться, как реализовать и порекомендую инструменты для удобной работы. Статья ориентирована на начальный и средний уровни. В конце Вас ждёт небольшой бонус. Всем заинтересованным добро пожаловать под кат.

Что это?

SQLite это легковесная, встраиваемая [1] и абсолютно самодостаточная [2] реляционная база данных. Она является самой распространённой [3] SQL-базой данных, по миру насчитывается не менее 500 млн. установок, это по сравнению со 100 млн. деплоев остальных SQL-баз данных. Используется в таких проектах, как Mozilla Firefox, Chrome, Skype, Windows Phone 8, iOS, Android, Symbian и прочие, и прочие… И самое главное она бесплатна, с открытым исходным кодом, а также имеет 100% покрытие тестами. Обо всём этом вы можете узнать на официальном сайте SQLite [4] и в постах на хабре [5].

Зачем?

Отмечу, что в нашем небольшом отделе почти у всех стоят разные ОС, и поскольку для нас важна взаимозаменяемость, мы старались выбирать кроссплатформенные решения.
Для нас SQLite был хорошим вариантом для хранения внешней информации — ресурсов, конфигурационных настроек, локализации. От внешних xml-подобных файлов мы отказались сразу, из-за проблем с переносом на разные устройства, раздутости и медленности. Целесообразность использования SQLite для Вашего проекта можно посмотреть здесь [6].

Как?

Для создания и редактирования БД наш выбор пал на SQLite Manager [7] — это плагин для Firefox, он бесплатный, удобный и кроссплатформенный. Единственное, что мне не понравилось — это приходилось дописывать SQL запрос на создание таблицы для добавления внешних ключей, а также невозможность редактирования записей в составленном VIEW из нескольких таблиц. А в остальном всё очень наглядно. Можно даже экспериментировать с SQL запросами к вашей БД. На выходе вы получаете один файлик, расширение которого можете указать сами (.db, .sqlite, .bytes и пр.), но Unity понимает только «.bytes».

Ещё один важный момент. Размещение в БД бинарников по типу картинок, музыки, видео является плохой практикой. Грубо говоря, всё что весит более 100 kb должно находиться в локальной папке, а в БД вы прописываете только пути. Иначе скорость чтения бинарника из базы становится больше [8], чем его загрузка локально.

Пришло время теперь разместить это всё в нашем Unity проекте. Для использования SQLite качаем библиотеки sqlite.dll [9] (для Win, iOS и MacOS) и sqlite.os [10] (для Android). Размещаем библиотеки здесь — Assets/Plugins/sqlite.dll и Assets/Plugins/Android/sqlite.so. Ежели папочки Plugins нет, то создаём её. Созданную БД (назовём её к примеру db.bytes) кладём в папочку Assets/StreamingAssets (создаём, если отсутствует). В итоге после деплоя, наша база окажется здесь:

Win и Mac OS:

Application.dataPath + "/StreamingAssets/db.bytes"

iOS:

Application.dataPath + "/Raw/db.bytes"

а вот на Android будет упакована в apk файл приложения:

"jar:file://" + Application.dataPath + "!/assets/db.bytes".

Вам потребуется используя WWW класс, чтобы загрузить базу, а затем скопировать в папку Application.persistentDataPath + "/".

Но эти директории обладают только правами для чтения (кроме Android'a), если же вам потребуется записать что-либо в базу, её необходимо переместить сюда:

Win и Mac OS:

Application.dataPath + "/db.bytes"

iOS:

string path = Application.dataPath.Substring(0, Application.dataPath.LastIndexOf("/"));
path = path.Substring(0, path.LastIndexOf("/")) + "/Documents/db.bytes";

или так

string path = Application.dataPath.Substring(0, Application.dataPath.length - 5);
path = path.Substring(0, path.LastIndexOf("/")) + "/Documents/db.bytes";

или так

string path = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal)  + "/db.bytes";

Про Android написано выше.

Затем подключаем пакет System.IO и пишем

File.Copy(openPath, savePath);

для Android'a соответственно

WWW www = new WWW(openPath);
while(!www .isDone) {} // тут очень внимательно, используйте корутины
File.WriteAllBytes(savePath, www.bytes);

Ну и бинарники ресурсов: модели, видео, музыка и т. д. кладём в папочку Assets/Resources/. После билда они упаковываются в бинарник resources.assets. А в приложении мы загружаем их — Resources.Load(String path) [11]. Ну например, мы положили звук в папочку Assets/Resources/Sounds/sound1.mp3, в базе у нас такая запись Sounds/sound1.mp3, и в приложении это будет выглядеть так

AudioClip a = Resources.Load("Sounds/sound1.mp3") as AudioClip;

Теперь настало время считать данные из нашей базы данных. Не люблю я писать SQL запросы и парсить сырые данные в объекты, поэтому специально для SQLite мы нашли opensource проект SQLite-net [12] ORM, это библиотека объёктно-реляционного отображения. Это технология, которая связывает базу данных с концепциями объектно-ориентированного программирования. Здесь есть поддержка Linq, например, можно сделать выборку:

public class Favorite 
{
	[PrimaryKey, AutoIncrement]
	public int Id { get; set; }
	public int UserId { get; set; }
	public string Url { get; set; }
}

public Favorite[] GetFavorites(SQLiteConnection c, int id)
{
	var q = from f in c.Table<Favorite>()
				where f.UserId == id
				select f;
	return q.ToArray();
}

или редактировать:

public void AddFavorite(SQLiteConnection c, string url, int id)
{
	var fav = new Favorite() 
	{
		UserId = id,
		Url = url
	};
    c.Insert(fav);
}

Но Linq поддерживается не в полном объёме, например, не поддерживается JOIN, поэтому для сложных запросов придётся всё-таки писать SQL код.

Где мой бонус?

Ну в принципе самое главное я написал. Теперь обещанный бонус. Предлагаю вам опробовать SQLite в своём проекте, для решения задачи локализации.
Имеем базу данных:
Диаграмма базы данных
Для просмотра, редактирования и создания мы разработали специальную тулзу для локализаторов, которую я тоже выкладываю (Adobe Air build для Win и Mac OS): cсылка [13]. Дерзайте!

Спасибо за внимание, жду ваших отзывов.

Автор: ierostenko

Источник [14]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/unity3d/35632

Ссылки в тексте:

[1] встраиваемая: http://www.sqlite.org/serverless.html

[2] самодостаточная: http://www.sqlite.org/selfcontained.html

[3] самой распространённой: http://www.sqlite.org/mostdeployed.html

[4] SQLite: http://www.sqlite.org/

[5] постах на хабре: http://habrahabr.ru/post/149356/

[6] здесь: http://www.sqlite.org/whentouse.html

[7] SQLite Manager: https://addons.mozilla.org/ru/firefox/addon/sqlite-manager/

[8] больше: http://www.sqlite.org/intern-v-extern-blob.html

[9] sqlite.dll: http://www.sqlite.org/download.html

[10] sqlite.os: http://forum.unity3d.com/threads/97043-Sqlite-for-Android-help-please?p=686204#13

[11] Resources.Load(String path): http://docs.unity3d.com/Documentation/ScriptReference/Resources.Load.html

[12] SQLite-net: https://github.com/praeclarum/sqlite-net

[13] cсылка: https://www.dropbox.com/s/jqof4yctm5htp6g/habr.zip

[14] Источник: http://habrahabr.ru/post/181239/