Pull to refresh

Unity3d + SQLite

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

Что это?

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

Зачем?

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

Как?

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

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

Пришло время теперь разместить это всё в нашем Unity проекте. Для использования SQLite качаем библиотеки sqlite.dll (для Win, iOS и MacOS) и sqlite.os (для 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). Ну например, мы положили звук в папочку Assets/Resources/Sounds/sound1.mp3, в базе у нас такая запись Sounds/sound1.mp3, и в приложении это будет выглядеть так
AudioClip a = Resources.Load("Sounds/sound1.mp3") as AudioClip;

Теперь настало время считать данные из нашей базы данных. Не люблю я писать SQL запросы и парсить сырые данные в объекты, поэтому специально для SQLite мы нашли opensource проект SQLite-net 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сылка. Дерзайте!

Спасибо за внимание, жду ваших отзывов.
Tags:
Hubs:
+10
Comments21

Articles

Change theme settings