Unity3D и MySQL

в 6:48, , рубрики: game development, Gamedev, mysql, unity3d, базы данных, Программирование, метки: , , , ,

Unity3D и MySQL
Сегодня мы разберёмся как подключить проект на Unity3D к БД MySQL.

Если точнее, то мы разберём как сохранять в БД состояния игровых объектов, а затем загружать их из БД. За основу взят гайд Джонатана Вуда для Unity 3.0.0f5 и MySQL 5.2.28. Он дополнен и адаптирован для 4-й версии Юнити.

Нам понадобятся:
1. Unity3D 4.x.
2. Доступ к БД MySQL.
3. Библиотека MySql.Data.dll.

В папке с проектом необходимо создать каталог Libraries, в который необходимо поместить библиотеку MySQL.Data.dll. Её можно скачать из этого архива, но если у вас уже установлен MySQL, то можете скопировать из c:Program Files (x86)MySQLMySQL Connector Net 6.0.3Assemblies.
Unity3D и MySQL
Чтобы избежать проблем совместимости версий сборок, а также сэкономить себе несколько часов времени и нервов (спасибо Джоэлю) установите уровень API совместимости Edit --> Project Settings --> Player -->Optimization-->Api Compatibility Level = .NET 2.0.
Unity3D и MySQL

Предварительная работа:
Unity3D и MySQL
1. Объекты состояние, которых необходимо сохранять помечаем тэгом «Savable».
Unity3D и MySQL
2. Создаём таблицу в БД, в которой будет храниться информация об объектах.

Чтобы пользоваться новой библиотекой добавьте в начало скрипта:

using MySql.Data; 
using MySql.Data.MySqlClient; 

А также не забудьте прописать параметры подключения в переменную:

	// MySQL настройки 
	string constr = "Server=localhost;Database=demo;User ID=demo;Password=demo;Pooling=true;CharSet=utf8;"; 

Создаём структуру, в которой будет храниться информация об объектах:

	// Названия синхронизируемых полей таблицы в БД
	string ID, Name, levelname, objectType; 
	float posx, posy, posz, tranx, trany, tranz; 
	// описание структуры синхронизируемых данных
	public struct data 
	{ 
		public int UID; 
		public string ID, Name, levelname, objectType; 
		public float posx, posy, posz, tranx, trany, tranz; 
	} 
	// коллекция в которую будут записываться данные о синхронизируемых объектах
	List<data> _GameItems;

При запуске скрипт подключается к БД, а при выключении разрывает соединение:

	void Awake() 
	{ 
		try 
		{ 
			// установка элемента соединения 
			con = new MySqlConnection(constr); 
 
			// посмотрим, сможем ли мы установить соединение 
			con.Open(); 	
			Debug.Log("Connection State: " + con.State); 
		} 
		catch (IOException ex)  {Debug.Log(ex.ToString());} 
	} 

void OnApplicationQuit() 
	{ 
		Debug.Log("killing con"); 
		if (con != null) 
		{ 
			// Конечно, правильнее использовать:
			// if (con.State != ConnectionState.Closed) 
			// но из-за проблем с версиями сборок приходится использовать костыли
			if (con.State.ToString()!="Closed")
			con.Close(); 
			con.Dispose(); 
		} 
	}

Есть две процедуры, отвечающие за работу со объектами на сцене:

prepDate - готовит данные для записи в БД

/// Этот метод подготавливает данные для записи в БД 
void prepData() 
	{ 
		bodies = GameObject.FindGameObjectsWithTag("Savable"); 
		_GameItems = new List<data>(); 
		data itm; 
		foreach (GameObject body in bodies) 
		{ 
			itm = new data(); 
			itm.ID = body.name + "_" + body.GetInstanceID(); 
			itm.Name = body.name; 
			itm.levelname = Application.loadedLevelName; 
			itm.objectType = body.name.Replace("(Clone)", ""); 
			itm.posx = body.transform.position.x; 
			itm.posy = body.transform.position.y; 
			itm.posz = body.transform.position.z; 
			itm.tranx = body.transform.rotation.x; 
			itm.trany = body.transform.rotation.y; 
			itm.tranz = body.transform.rotation.z; 
			_GameItems.Add(itm); 
		}
		Debug.Log("Items in collection: " + _GameItems.Count); 
	}
} 

loadDate - загружает объекты на сцену

/// Этот метод устанавливает загруженные объекты на сцене 
void loadData() 
	{ 
		// Удаляем все лишние объекты со сцены
		bodies = GameObject.FindGameObjectsWithTag("Savable");
		DestroyObject(bodies);
		// Создаём сохранённые в БД объекты
		if (_GameItems != null)
		{
			if (_GameItems.Count > 0)
			{
				foreach (data itm in _GameItems)
				{
					if (itm.objectType="CUBE") 
					{Instantiate(mCUBE, new Vector3(itm.posx, itm.posy , itm.posz),Quaternion.Euler(itm.tranx, itm.trany, itm.tranz));}
					else if (itm.objectType="SPHERE") 
					{Instantiate(mSPHERE, new Vector3(itm.posx, itm.posy , itm.posz),Quaternion.Euler(itm.tranx, itm.trany, itm.tranz));}
					else if (itm.objectType="TRIANGLE") 
					{Instantiate(mTRIANGLE, new Vector3(itm.posx, itm.posy , itm.posz),Quaternion.Euler(itm.tranx, itm.trany, itm.tranz));}
				}
			}
		}

	}
} 

А также четыре основных процедуры, отвечающие за работу с БД:

InsertEntries - вставка новой записи в таблицу.

// Вставка новой записи в таблицу
void InsertEntries() 
	{ 
	prepData(); 
	string query = string.Empty; 
	// Вылавливаем ошибки 
	try 
	{ 
		query = "INSERT INTO demo_table (ID, Name, levelname, objectType, posx, posy, posz, tranx, trany, tranz) VALUES (?ID, ?Name, ?levelname, ?objectType, ?posx, ?posy, ?posz, ?tranx, ?trany, ?tranz)";
		if (con.State.ToString()!="Open")
		con.Open(); 
		using (con) 
		{
		foreach (data itm in _GameItems) 
			{ 
			using (cmd = new MySqlCommand(query, con)) 
				{ 
					MySqlParameter oParam = cmd.Parameters.Add("?ID", MySqlDbType.VarChar); 
					oParam.Value = itm.ID; 
					MySqlParameter oParam1 = cmd.Parameters.Add("?Name", MySqlDbType.VarChar); 
					oParam1.Value = itm.Name; 
					MySqlParameter oParam2 = cmd.Parameters.Add("?levelname", MySqlDbType.VarChar); 
					oParam2.Value = itm.levelname; 
					MySqlParameter oParam3 = cmd.Parameters.Add("?objectType", MySqlDbType.VarChar); 
					oParam3.Value = itm.objectType; 
					MySqlParameter oParam4 = cmd.Parameters.Add("?posx", MySqlDbType.Float); 
					oParam4.Value = itm.posx; 
					MySqlParameter oParam5 = cmd.Parameters.Add("?posy", MySqlDbType.Float); 
					oParam5.Value = itm.posy; 
					MySqlParameter oParam6 = cmd.Parameters.Add("?posz", MySqlDbType.Float);
					oParam6.Value = itm.posz; 
					MySqlParameter oParam7 = cmd.Parameters.Add("?tranx", MySqlDbType.Float); 
					oParam7.Value = itm.tranx; 
					MySqlParameter oParam8 = cmd.Parameters.Add("?trany", MySqlDbType.Float); 
					oParam8.Value = itm.trany; 
					MySqlParameter oParam9 = cmd.Parameters.Add("?tranz", MySqlDbType.Float); 
					oParam9.Value = itm.tranz; 
					cmd.ExecuteNonQuery(); 
				}
			}
		}
	}
	catch (IOException ex) 
	{ 
		Debug.Log(ex.ToString()); 
	}
	finally {} 
	}

UpdateEntries- обновление существующих записей в таблице.
	// Обновление существующих записей в таблице 
	void UpdateEntries() 
	{ 
	prepData(); 
	string query = string.Empty; 
	// Вылавливаем ошибки
	try 
	{
		query = "UPDATE demo_table SET ID=?ID, Name=?Name, levelname=?levelname, objectType=?objectType, posx=?posx, posy=?posy, posz=?posz, tranx=?tranx, trany=?trany, tranz=?tranz WHERE iddemo_table=?UID";
		if (con.State.ToString()!="Open")
		con.Open(); 
		using (con) 
		{
		foreach (data itm in _GameItems) 
			{
				using (cmd = new MySqlCommand(query, con)) 
                    		{
					MySqlParameter oParam = cmd.Parameters.Add("?ID", MySqlDbType.VarChar); 
					oParam.Value = itm.ID; 
					MySqlParameter oParam1 = cmd.Parameters.Add("?Name", MySqlDbType.VarChar); 
					oParam1.Value = itm.Name; 
					MySqlParameter oParam2 = cmd.Parameters.Add("?levelname", MySqlDbType.VarChar); 
					oParam2.Value = itm.levelname; 
					MySqlParameter oParam3 = cmd.Parameters.Add("?objectType", MySqlDbType.VarChar); 
					oParam3.Value = itm.objectType; 
					MySqlParameter oParam4 = cmd.Parameters.Add("?posx", MySqlDbType.Float); 
					oParam4.Value = itm.posx; 
					MySqlParameter oParam5 = cmd.Parameters.Add("?posy", MySqlDbType.Float); 
					oParam5.Value = itm.posy; 
					MySqlParameter oParam6 = cmd.Parameters.Add("?posz", MySqlDbType.Float);
					oParam6.Value = itm.posz; 
					MySqlParameter oParam7 = cmd.Parameters.Add("?tranx", MySqlDbType.Float); 
					oParam7.Value = itm.tranx; 
					MySqlParameter oParam8 = cmd.Parameters.Add("?trany", MySqlDbType.Float); 
					oParam8.Value = itm.trany; 
					MySqlParameter oParam9 = cmd.Parameters.Add("?tranz", MySqlDbType.Float); 
					oParam9.Value = itm.tranz; 
					cmd.ExecuteNonQuery(); 
				} 
			}
		}
	}
	catch (IOException ex) {Debug.Log(ex.ToString());} 
	finally {} 
	}

DeleteEntries- удаление записей из таблицы.

// Удаляем запись из таблицы 
void DeleteEntries() 
	{ 
	string query = string.Empty; 
	// Вылавливаем ошибки
	try 
	{ 
		// лучше всего если вы знаете ID записи, которую необходимо удалить
		//----------------------------------------------------------------------- 
		// query = "DELETE FROM demo_table WHERE iddemo_table=?UID"; 
		// MySqlParameter oParam = cmd.Parameters.Add("?UID", MySqlDbType.Int32); 
		// oParam.Value = 0; 
		//----------------------------------------------------------------------- 
		query = "DELETE FROM demo_table WHERE iddemo_table"; 
		if (con.State.ToString()!="Open")
		con.Open(); 
		using (con) 
		{ 
			using (cmd = new MySqlCommand(query, con)) 
			{ 
				cmd.ExecuteNonQuery(); 
                	} 
		}
	}
	catch (IOException ex) {Debug.Log(ex.ToString());}
	finally {}
	}

ReadEntries- чтение всех записей из таблицы.

// Чтение всех записей из таблицы 
void ReadEntries() 
	{
		string query = string.Empty; 
		if (_GameItems == null) 
		_GameItems = new List<data>(); 
		if (_GameItems.Count > 0) 
		_GameItems.Clear(); 
		// Отлавливаем ошибки 
		try
		{
			query = "SELECT * FROM view_demo"; 
			if (con.State.ToString()!="Open")
			con.Open(); 
			using (con) 
			{
				using (cmd = new MySqlCommand(query, con)) 
				{
					rdr = cmd.ExecuteReader(); 
					if(rdr.HasRows) 
					while (rdr.Read()) 
					{
						data itm = new data(); 
						itm.UID = int.Parse(rdr["iddemo_table"].ToString()); 
						itm.ID = rdr["ID"].ToString(); 
						itm.levelname = rdr["levelname"].ToString(); 
						itm.Name = rdr["Name"].ToString(); 
						itm.objectType = rdr["objectType"].ToString(); 
						itm.posx = float.Parse(rdr["posx"].ToString()); 
						itm.posy = float.Parse(rdr["posy"].ToString());
						itm.posz = float.Parse(rdr["posz"].ToString()); 
						itm.tranx = float.Parse(rdr["tranx"].ToString()); 
						itm.trany = float.Parse(rdr["trany"].ToString()); 
						itm.tranz = float.Parse(rdr["tranz"].ToString()); 
						_GameItems.Add(itm); 
					}
					rdr.Dispose(); 
				}
			}
		}
	catch (IOException ex) {Debug.Log(ex.ToString());}
	finally {}
	}

Остаётся только сделать пару кнопок для загрузки и сохранения сцены:

	// Кнопки загрузки и сохранения 
	void OnGUI() 
	{
	if (GUI.Button(new Rect(10, 70, 50, 30), "Save") && !saving) 
		{ 
			saving = true; 
			// Для начала очистим таблицу 
			DeleteEntries(); 
			// теперь сохраним информацию о сцене
			InsertEntries(); 
			// можно также использовать обновление если известен ID уже сохранённого элемента

			saving = false; 
		}
	if (GUI.Button(new Rect(10, 110, 50, 30), "Load") && !loading) 
		{ 
			loading = true; 
			// считаем информацию из БД
			ReadEntries(); 
			// создадим загруженные объекты
			loadData();
			// теперь отобразим информацию из лога
			LogGameItems(); 
			loading = false; 
		}
	} 

Вот в общем-то и всё. В комментах приветствуются примечания и дополнения.

Весь скрипт

using UnityEngine; 
using MySql.Data; 
using MySql.Data.MySqlClient; 
using System.IO; 
using System.Collections; 
using System.Collections.Generic; 
 
public class MySQLCS : MonoBehaviour 
{ 
	public GameObject mCUBE;
	public GameObject mSPHERE;
	public GameObject mTRIANGLE;

	bool saving = false; 
	bool loading = false; 

	// MySQL настройки 
	string constr = "Server=localhost;Database=demo;User ID=demo;Password=demo;Pooling=true;CharSet=utf8;"; 
	// соединение 
	MySqlConnection con = null; 
	// команда к БД
	MySqlCommand cmd = null; 
	// чтение
	MySqlDataReader rdr = null; 
	// ошибки
	MySqlError er = null; 

	// массив синхронизируемых игровых объектов
	GameObject[] bodies; 

	// Названия синхронизируемых полей таблицы в БД
	string ID, Name, levelname, objectType; 
	float posx, posy, posz, tranx, trany, tranz; 
	// описание структуры синхронизируемых данных
	public struct data 
	{ 
		public int UID; 
		public string ID, Name, levelname, objectType; 
		public float posx, posy, posz, tranx, trany, tranz; 
	} 
	// коллекция в которую будут записываться данные о синхронизируемых объектах
	List<data> _GameItems;
	void Awake() 
	{ 
		try 
		{ 
			// установка элемента соединения 
			con = new MySqlConnection(constr); 
 
			// посмотрим, сможем ли мы установить соединение 
			con.Open(); 	
			Debug.Log("Connection State: " + con.State); 
		} 
		catch (IOException ex)  {Debug.Log(ex.ToString());} 
	} 

void OnApplicationQuit() 
	{ 
		Debug.Log("killing con"); 
		if (con != null) 
		{ 
			// Конечно, правильнее использовать:
			// if (con.State != ConnectionState.Closed) 
			// но из-за проблем с версиями сборок приходится использовать костыли
			if (con.State.ToString()!="Closed")
			con.Close(); 
			con.Dispose(); 
		} 
	}

	// Use this for initialization 
	void Start() 
	{
 
	}
 
	// Update is called once per frame 
	void Update() 
	{

	}
 
 
	// Кнопки загрузки и сохранения 
	void OnGUI() 
	{
	if (GUI.Button(new Rect(10, 70, 50, 30), "Save") && !saving) 
		{ 
			saving = true; 
			// Для начала очистим таблицу 
			DeleteEntries(); 
			// теперь сохраним информацию о сцене
			InsertEntries(); 
			// можно также использовать обновление если известен ID уже сохранённого элемента

			saving = false; 
		}
	if (GUI.Button(new Rect(10, 110, 50, 30), "Load") && !loading) 
		{ 
			loading = true; 
			// считаем информацию из БД
			ReadEntries(); 
			// создадим загруженные объекты
			loadData();
			// теперь отобразим информацию из лога
			LogGameItems(); 
			loading = false; 
		}
	} 

// Вставка новой записи в таблицу
void InsertEntries() 
	{ 
	prepData(); 
	string query = string.Empty; 
	// Вылавливаем ошибки 
	try 
	{ 
		query = "INSERT INTO demo_table (ID, Name, levelname, objectType, posx, posy, posz, tranx, trany, tranz) VALUES (?ID, ?Name, ?levelname, ?objectType, ?posx, ?posy, ?posz, ?tranx, ?trany, ?tranz)";
		if (con.State.ToString()!="Open")
		con.Open(); 
		using (con) 
		{
		foreach (data itm in _GameItems) 
			{ 
			using (cmd = new MySqlCommand(query, con)) 
				{ 
					MySqlParameter oParam = cmd.Parameters.Add("?ID", MySqlDbType.VarChar); 
					oParam.Value = itm.ID; 
					MySqlParameter oParam1 = cmd.Parameters.Add("?Name", MySqlDbType.VarChar); 
					oParam1.Value = itm.Name; 
					MySqlParameter oParam2 = cmd.Parameters.Add("?levelname", MySqlDbType.VarChar); 
					oParam2.Value = itm.levelname; 
					MySqlParameter oParam3 = cmd.Parameters.Add("?objectType", MySqlDbType.VarChar); 
					oParam3.Value = itm.objectType; 
					MySqlParameter oParam4 = cmd.Parameters.Add("?posx", MySqlDbType.Float); 
					oParam4.Value = itm.posx; 
					MySqlParameter oParam5 = cmd.Parameters.Add("?posy", MySqlDbType.Float); 
					oParam5.Value = itm.posy; 
					MySqlParameter oParam6 = cmd.Parameters.Add("?posz", MySqlDbType.Float);
					oParam6.Value = itm.posz; 
					MySqlParameter oParam7 = cmd.Parameters.Add("?tranx", MySqlDbType.Float); 
					oParam7.Value = itm.tranx; 
					MySqlParameter oParam8 = cmd.Parameters.Add("?trany", MySqlDbType.Float); 
					oParam8.Value = itm.trany; 
					MySqlParameter oParam9 = cmd.Parameters.Add("?tranz", MySqlDbType.Float); 
					oParam9.Value = itm.tranz; 
					cmd.ExecuteNonQuery(); 
				}
			}
		}
	}
	catch (IOException ex) 
	{ 
		Debug.Log(ex.ToString()); 
	}
	finally {} 
	}

	// Обновление существующих записей в таблице 
	void UpdateEntries() 
	{ 
	prepData(); 
	string query = string.Empty; 
	// Вылавливаем ошибки
	try 
	{
		query = "UPDATE demo_table SET ID=?ID, Name=?Name, levelname=?levelname, objectType=?objectType, posx=?posx, posy=?posy, posz=?posz, tranx=?tranx, trany=?trany, tranz=?tranz WHERE iddemo_table=?UID";
		if (con.State.ToString()!="Open")
		con.Open(); 
		using (con) 
		{
		foreach (data itm in _GameItems) 
			{
				using (cmd = new MySqlCommand(query, con)) 
                    		{
					MySqlParameter oParam = cmd.Parameters.Add("?ID", MySqlDbType.VarChar); 
					oParam.Value = itm.ID; 
					MySqlParameter oParam1 = cmd.Parameters.Add("?Name", MySqlDbType.VarChar); 
					oParam1.Value = itm.Name; 
					MySqlParameter oParam2 = cmd.Parameters.Add("?levelname", MySqlDbType.VarChar); 
					oParam2.Value = itm.levelname; 
					MySqlParameter oParam3 = cmd.Parameters.Add("?objectType", MySqlDbType.VarChar); 
					oParam3.Value = itm.objectType; 
					MySqlParameter oParam4 = cmd.Parameters.Add("?posx", MySqlDbType.Float); 
					oParam4.Value = itm.posx; 
					MySqlParameter oParam5 = cmd.Parameters.Add("?posy", MySqlDbType.Float); 
					oParam5.Value = itm.posy; 
					MySqlParameter oParam6 = cmd.Parameters.Add("?posz", MySqlDbType.Float);
					oParam6.Value = itm.posz; 
					MySqlParameter oParam7 = cmd.Parameters.Add("?tranx", MySqlDbType.Float); 
					oParam7.Value = itm.tranx; 
					MySqlParameter oParam8 = cmd.Parameters.Add("?trany", MySqlDbType.Float); 
					oParam8.Value = itm.trany; 
					MySqlParameter oParam9 = cmd.Parameters.Add("?tranz", MySqlDbType.Float); 
					oParam9.Value = itm.tranz; 
					cmd.ExecuteNonQuery(); 
				} 
			}
		}
	}
	catch (IOException ex) {Debug.Log(ex.ToString());} 
	finally {} 
	}

// Удаляем запись из таблицы 
void DeleteEntries() 
	{ 
	string query = string.Empty; 
	// Вылавливаем ошибки
	try 
	{ 
		// лучше всего если вы знаете ID записи, которую необходимо удалить
		//----------------------------------------------------------------------- 
		// query = "DELETE FROM demo_table WHERE iddemo_table=?UID"; 
		// MySqlParameter oParam = cmd.Parameters.Add("?UID", MySqlDbType.Int32); 
		// oParam.Value = 0; 
		//----------------------------------------------------------------------- 
		query = "DELETE FROM demo_table WHERE iddemo_table"; 
		if (con.State.ToString()!="Open")
		con.Open(); 
		using (con) 
		{ 
			using (cmd = new MySqlCommand(query, con)) 
			{ 
				cmd.ExecuteNonQuery(); 
                	} 
		}
	}
	catch (IOException ex) {Debug.Log(ex.ToString());}
	finally {}
	}

// Чтение всех записей из таблицы 
void ReadEntries() 
	{
		string query = string.Empty; 
		if (_GameItems == null) 
		_GameItems = new List<data>(); 
		if (_GameItems.Count > 0) 
		_GameItems.Clear(); 
		// Отлавливаем ошибки 
		try
		{
			query = "SELECT * FROM view_demo"; 
			if (con.State.ToString()!="Open")
			con.Open(); 
			using (con) 
			{
				using (cmd = new MySqlCommand(query, con)) 
				{
					rdr = cmd.ExecuteReader(); 
					if(rdr.HasRows) 
					while (rdr.Read()) 
					{
						data itm = new data(); 
						itm.UID = int.Parse(rdr["iddemo_table"].ToString()); 
						itm.ID = rdr["ID"].ToString(); 
						itm.levelname = rdr["levelname"].ToString(); 
						itm.Name = rdr["Name"].ToString(); 
						itm.objectType = rdr["objectType"].ToString(); 
						itm.posx = float.Parse(rdr["posx"].ToString()); 
						itm.posy = float.Parse(rdr["posy"].ToString());
						itm.posz = float.Parse(rdr["posz"].ToString()); 
						itm.tranx = float.Parse(rdr["tranx"].ToString()); 
						itm.trany = float.Parse(rdr["trany"].ToString()); 
						itm.tranz = float.Parse(rdr["tranz"].ToString()); 
						_GameItems.Add(itm); 
					}
					rdr.Dispose(); 
				}
			}
		}
	catch (IOException ex) {Debug.Log(ex.ToString());}
	finally {}
	}

/// Запишем в лог всё что было считано из БД
void LogGameItems() 
	{ 
		if (_GameItems != null) 
		{
			if (_GameItems.Count > 0) 
			{
				foreach (data itm in _GameItems) 
				{
					Debug.Log("UID: " + itm.UID); 
					Debug.Log("ID: " + itm.ID); 
					Debug.Log("levelname: " + itm.levelname); 
					Debug.Log("Name: " + itm.Name); 
					Debug.Log("objectType: " + itm.objectType); 
					Debug.Log("posx: " + itm.posx); 
					Debug.Log("posy: " + itm.posy); 
					Debug.Log("posz: " + itm.posz); 
					Debug.Log("tranx: " + itm.tranx); 
					Debug.Log("trany: " + itm.trany); 
					Debug.Log("tranz: " + itm.tranz); 
				}
			}
		}
	}

/// Этот метод подготавливает данные для записи в БД 
void prepData() 
	{ 
		bodies = GameObject.FindGameObjectsWithTag("Savable"); 
		_GameItems = new List<data>(); 
		data itm; 
		foreach (GameObject body in bodies) 
		{ 
			itm = new data(); 
			itm.ID = body.name + "_" + body.GetInstanceID(); 
			itm.Name = body.name; 
			itm.levelname = Application.loadedLevelName; 
			itm.objectType = body.name.Replace("(Clone)", ""); 
			itm.posx = body.transform.position.x; 
			itm.posy = body.transform.position.y; 
			itm.posz = body.transform.position.z; 
			itm.tranx = body.transform.rotation.x; 
			itm.trany = body.transform.rotation.y; 
			itm.tranz = body.transform.rotation.z; 
			_GameItems.Add(itm); 
		}
		Debug.Log("Items in collection: " + _GameItems.Count); 
	}
} 

/// Этот метод устанавливает загруженные объекты на сцене 
void loadData() 
	{ 
		// Удаляем все лишние объекты со сцены
		bodies = GameObject.FindGameObjectsWithTag("Savable");
		DestroyObject(bodies);
		// Создаём сохранённые в БД объекты
		if (_GameItems != null)
		{
			if (_GameItems.Count > 0)
			{
				foreach (data itm in _GameItems)
				{
					if (itm.objectType="CUBE") {Instantiate(mCUBE, new Vector3(itm.posx, itm.posy , itm.posz),Quaternion.Euler(itm.tranx, itm.trany, itm.tranz));}
					else if (itm.objectType="SPHERE") {Instantiate(mSPHERE, new Vector3(itm.posx, itm.posy , itm.posz),Quaternion.Euler(itm.tranx, itm.trany, itm.tranz));}
					else if (itm.objectType="TRIANGLE") {Instantiate(mTRIANGLE, new Vector3(itm.posx, itm.posy , itm.posz),Quaternion.Euler(itm.tranx, itm.trany, itm.tranz));}
				}
			}
		}

	}
} 

Автор: malan

Источник

  1. не фига не работает:

    не фига не работает

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js