Хранение данных в игре

Аватара пользователя
Vasaka
MOSC Team
Сообщения: 3195
Регистрация: 24 янв 2011

Хранение данных в игре

Сообщение Vasaka »

krupennikov писал(а): 23 ноя 2011, 20:51Если речь идет об однопользовательской игре, то вопрос такой: где легче изменить данные - в ОЗУ или на жестком диске? В любом случае, при большом желании можно сделать и то и другое, но не вижу смысла для игрока, для него самого пропадет интерес к игре. Если речь идет о многопользовательской игре, то для этого в любом случае будет писаться отдельный код и использоваться реальная БД с сервера. Как по мне, так удобнее использовать вместо List именно DataTable, и делать выборку данных с реальной БД также удобнее с помощью DataTable (DataSet).

В мануале к Юнити написано, что один и тот же код используется для однопользовательской и многопользовательской игры.

Я сейчас попробую поискать где это было написано.
AndreyKl
Сообщения: 51
Регистрация: 22 фев 2011

Хранение данных в игре

Сообщение AndreyKl »

Vasaka писал(а): 23 ноя 2011, 21:50В мануале к Юнити написано, что один и тот же код используется для однопользовательской и многопользовательской игры.
Это не от Unity зависит, но для всех игроков действительно будет использоваться один и тот же код помимо хоста/арбитра или когонить со спецификой доступа - он единственный будет иметь доступ к открытию нового хода. во всяких FPS код может был бы один (хотя и там часто можно сервер выделить).
Конечно можно реализовать и общий код для всех, просто разделить права доступа. но по мне проще сделать формочку с строчкой для пароля и кнопочкой ран хосту.

Так же для пошаговых стратегий для мультика придется переделывать всю систему, дабы предотвратить сейв/лоад (пока само правильное решение в серии Space empires) - но графический движек всеравно останется тот же.
AndreyKl
Сообщения: 51
Регистрация: 22 фев 2011

Хранение данных в игре

Сообщение AndreyKl »

Networked Multiplayer
Реализация сети в реальном времени — сложная задача, но мы сделали её максимально простой. В этом параграфе будут рассмотрены основные сетевые концепции и специфичные для Unity детали. Настоятельно рекомендуем внимательно прочитать эту главу всем пользователям, которые ранее не создавали сетевых игр.
Ключевым аспектом здесь является реальное время, которого у нас нет в помине. Для пошаговых игр мультиплеер вообще можно без сети делать - хоть на флешке файлы переноси (или подключайся к удаленной БД стандартными средствами если сейвы будут на основе БД).
Аватара пользователя
Vasaka
MOSC Team
Сообщения: 3195
Регистрация: 24 янв 2011

Хранение данных в игре

Сообщение Vasaka »

AndreyKl писал(а): 24 ноя 2011, 18:38Ключевым аспектом здесь является реальное время, которого у нас нет в помине. Для пошаговых игр мультиплеер вообще можно без сети делать - хоть на флешке файлы переноси (или подключайся к удаленной БД стандартными средствами если сейвы будут на основе БД).

Ясно.

Ты уже пробовал поработать с БД на Юнити?
4 гига, это ограничение на размер БД?
krupennikov
Сообщения: 53
Регистрация: 25 янв 2011

Хранение данных в игре

Сообщение krupennikov »

AndreyKl писал(а): 23 ноя 2011, 21:49вот тут уж поверьте наслово, дататейбл по сравнению с ентити нервно курит в сторонке - через ентити по всем элементам базы можно пробегаться не прибегая к помощи linq, даже выборки делать, визуально никакого отличия от List нет помимо немного переименованных Add, наличия команд save/refresh и ивент обновления(кстати про рефрешь узнал только когда обнаружил, что программа оперирует с элементами удаленными из БД 2-3 часа назад).


С ентити я ни разу не работал, поэтому спорить с этим не буду. Возможно это действительно так. И если это так, то готов отказаться от DataSet и в своих проектах. Андрей, если есть возмножность, выложи пример недожидаясь меня. У меня завал в работе. Я уже начал писать пример, но пишу перерывами... Даже выкладывал на ХэшКоде вопрос какую БД можно использовать так , чтобы не требовалась дополнительная установка платного ПО, и в тоже время можно было программно в шарпе создавать и изменять таблицы с нуля, а не лезть в сторонний редактор. SQL server мне не понравился. Если ентити то что я искал, то буду очень рад и надеяться на содействие в помощи его изучения с твоей стороны (надеюсь можно и на ТЫ, не люблю ВЫкать)
krupennikov
Сообщения: 53
Регистрация: 25 янв 2011

Хранение данных в игре

Сообщение krupennikov »

вот что сделал на скорую руку в два подхода по 15-20 мин. Но тут совсем малость и как говорится тема не раскрыта. Делал в C# Express 2010
AndreyKl
Сообщения: 51
Регистрация: 22 фев 2011

Хранение данных в игре

Сообщение AndreyKl »

Вот самый плешивенький пример на одну таблицу. Писать чтолибо сложнее пока не охота. Но приведу пример по связям на словах.
Если есть елемент car таблицы CarsSet (содержащая поле марок Marks_Id), и таблица MarksSet (содержашея имена марок), то чтобы узнать имя марки выбранной машины достаточно написать car.MarksSet.Name. Определить эффективность этого дества вызванного вне запросов Linq я не смог - по непонятной мне причине запросы к БД не всегда приходили даже при единичных вызовах поля Name (либо всё жутко оптимизировано и идет работа с ОЗУ, либо мелкософт жульничает и ввела обходной путь доступа к БД помимо SQL), для построения таблиц linq вытягивала эту информацию сразу.
Должен заметить, что уже вышел Ентити 4.1, я его как раз изучаю. Но и старый очень не плох, до тех пор, пока не нужно его напрямую привязывать к WPF binding (много мороки с отслеживанием обновления элементов как из-за самого биндинг так и необходимости refresh БД).
Базу (.sdf) ложить на диск C.

P.S. Регенерить базу не советую, для быстроты ввел кастомный код прямо в её класс - затреться при регенерации.
Все файлы в папке model были сгенерированны автоматически, никакого участия помимо добавленных 2 строк не принимал (просто лень было писать генерацию Id, так как в взятом шаблоне БД не проставил автоинкремент).
Изменение местоположения базы здесь через app.config, но при необходимости строку подключения можно передавать параметром.
P.P.S. У меня так же есть масштабный проэкт на базе Linq и Entity, где уже задействованы связи и т п. Могу скинуть его для ознакомления.
krupennikov
Сообщения: 53
Регистрация: 25 янв 2011

Хранение данных в игре

Сообщение krupennikov »

Андрей, твой файл скачал, но еще не смотрел.
Выкладываю немного дописанный файл DataTableSample.

Вот некоторые вырезки из кода:

Код: Выделить всё



#region Описание
/*
* Для добавления новой таблицы добавьте новый класс в проект BaseLibrary.
* Для добавления нового столбца добавьте новый параметр в необходимый
* класс проекта BaseLibrary, при этом уже имеющиеся данные останутся.
*/
#endregion

#region Метод запроса по определенному столбцу
/*
* Заполнение таблицы результата на запрос tableResult
* необходимо для вывода результата в форме поиска
* исключительно для наглядности. При отсутствии необходимости
* вывода результата для наглядности в виде таблицы, достаточно
* оставить только одну строку запроса такого формата:
* DataRow[] rows = table.Select("имя_столбца='значение'");
* либо, например, для вывода строк столбца 'Сила' со значением больше 10:
* DataRow[] rows = table.Select("Сила>10");
*/
public static DataTable Search(DataTable table, string parametr, string columnName)
{
//формируем запрос
string filter = string.Format("{0}='{1}'", columnName, parametr);
//объявляем новую таблицу для результата запроса
DataTable tableResult = new DataTable();
try
{
//выполняем запрос
var rows = table.Select(filter);

//заполняем таблицу результата столбцами
foreach (var column in rows[0].Table.Columns)
tableResult.Columns.Add(((DataColumn)column).ColumnName);

//заполняем таблицу результата строками
foreach (var row in rows)
{
DataRow r = tableResult.NewRow();
r.ItemArray = row.ItemArray;
tableResult.Rows.Add(r);
}

//возвращаем результат запроса в виде таблицы
return tableResult;
}
catch { return null; }
}

#endregion

#region Метод запроса по всем столбцам таблицы

public static DataTable Search(DataTable table, string parametr)
{
//создаем новую таблицу для результата запроса
DataTable tableResult = new DataTable();

//ЗАПОЛНЯЕМ СТОЛБЦЫ

//Выберите вариант заполнения

/*
// Вариант 1
// Заполнение с помощью List
List<DataColumn> columns = new List<DataColumn>();
columns.AddRange(table.Columns.Cast<DataColumn>());
tableResult.Columns.AddRange(columns.ToArray());
*/

/*
// Вариант 2
// Заполнение с помощью еще одного метода
var cols = (DataColumn[])table.Columns.Cast<DataColumn>().ToArray().Clone();
tableResult.Columns.AddRange(cols);
*/

// Вариант 3
// Заполнение с помощью цикла
foreach (var column in table.Columns)
tableResult.Columns.Add(((DataColumn)column).ColumnName);

//выполняем запрос по всем столбцам таблицы
foreach (var column in table.Columns)
{
try
{
var rows = (Search(table, parametr, ((DataColumn)column).ColumnName)).Rows;
for (int i =0;i<rows.Count;i++)
tableResult.Rows.Add(rows[I].ItemArray);
}
catch { continue; }
}

//возвращаем результат запроса в виде таблицы
return tableResult;
}

Как видно, для поиска значения в DataTable существует удобный метод Select, который возвращает массив строк DataRow[]. Теперь для изменения нужного нам параметра, достаточно написать:
rows[index]["параметр"] = значение;

Например, в таблице Planets нам надо изменить диаметр Земли, присвоив значение 1000. Скажем эта таблица принадлежит переменной table:

DataRow[] rows = table.Select("Имя='Земля'");
rows[0]["Диаметр"] = 1000;

А вот если, например, в таблице Planets нам надо изменить диаметр Земли, увеличив на 10, то число строк увеличится:

DataRow[] rows = table.Select("Имя='Земля'");
var value = (double)rows[0]["Диаметр"];
value += 10;
rows[0]["Диаметр"] = value;

Вот и все. А по поводу выборки из нескольких таблиц, напишу позже. Пора бежать...
krupennikov
Сообщения: 53
Регистрация: 25 янв 2011

Хранение данных в игре

Сообщение krupennikov »

Андрей, если не сложно, выложи что нибудь по изучению Entity. Либо ссылки на нормальное описание. На русском естесно

Добавлено через 58 минут 16 секунд
Выдержка из книги Троелсона:


Несмотря на удобство интерфейса LINQ to DataSet, следует помнить, что целью запроса LINQ являются данные, возвращенные из базы данных, а не сам механизм базы данных. В идеале хотелось бы строить запрос LINQ, который отправлялся бы на обработку непосредственно базе данных, и возвращал строго типизированные данные (именно это и позволяет достичь ADO.NET Entity Framework).
При использовании подключенного и автономного уровней ADO.NET всегда приходится помнить о физической структуре лежащей в основе базы данных. Необходимо знать схему каждой таблицы данных, писать сложные SQL-запросы для взаимодействия с данными таблиц и т.д. Это вынуждает писать довольно громоздкий код С#, поскольку С# существенно отличается от языка самой базы данных.
Вдобавок способ конструирования физической базы данных (администратором баз данных) полностью сосредоточен на таких конструкциях базы, как внешние ключи, представления и хранимые процедуры. Сложность баз данных, спроектированных администратором, может еще более возрастать, если администратор при этом заботится о безопасности и масштабируемости. Это также усложняет код С#, который приходится писать для взаимодействия с хранилищем данных. Платформа ADO.NET Entity Framework (EF) — это программная модель, которая пытается заполнить пробел между конструкциями базы данных и объектно-ориентированными конструкциями. Используя EF, можно взаимодействовать с реляционными базами данных, не имея дело с кодом SQL (при желании). Исполняющая среда EF генерирует подходящее операторы SQL, когда вы применяете запросы LINQ к строго типизированным классам.
На заметку! LINQ to Entities — это термин, описывающий применение запросов LINQ к сущностным объектам ADO.NET.
Другой возможный подход состоит в том, чтобы вместо обновления базы данных посредством нахождения строки, обновления строки и отправки строки обратно на обработку в пакете запросов SQL, просто изменять свойства объекта и сохранять его состояние. И в этом случае исполняющая среда EF обновляет базу данных автоматически.
В Microsoft считают ADO.NET Entity Framework новым членом семейства технологий доступа к данным, и не намерены заменять им подключенный и автономный уровни. Однако после недолгого использования EF часто отдается предпочтение этой развитой объектной модели перед относительно примитивным миром SQL-запросов и коллекций строк/столбцов.
Тем не менее, иногда в проектах .NET используются все три подхода, поскольку одна только модель EF чрезмерно усложняет код. Например, при построении внутреннего приложения, которому нужно взаимодействовать с единственной таблицей базы данных, подключенный уровень может применяться для запуска пакета хранимых процедур. Существенно выиграть от использования EF могут более крупные приложения, особенно если команда разработчиков уверено работает с LINQ. Как с любой новой технологией, следует знать, как (и когда) имеет смысл применять ADO.NET EF.
На заметку! Вспомните, что в .NET 3.5 появился API-интерфейс программирования баз данных под названием LINQ to SQL. Он был построен на основе концепции, близкой (даже очень близкой в смысле конструкций программирования) к ADO.NET ЕЕ Хотя LINQ to SQL формально еще существует, официальное мнение в Microsoft состоит в том, что теперь следует обращать внимание на EF, а не на LINQ to SQL.


Согласно этой выдержки, соглашусь с Андреем, что для использования масштабного проекта лучше использовать Entity для работы с Базой данных. Для менее масштабного проекта DataSet (DataTable) все таки имеет больше преимуществ перед Entity. Хотя мой проект, над которым я в данный момент работаю, менее масштабный (содержит 1 большую таблицу - основную, и несколько маленьких) буду переделывать под Entity, только ради полного и глубокого изучения Entity FrameWork.
Закрыто