Простой игровой магазин (локальный)

Суть здесь в том, что мы заранее определяем места, где будут появляться купленные объекты. Например, есть выделенный участок, на котором изначально просто фундамент дома, если совершается покупка, то фундамент заменяется другим объектом, то есть, готовым домом или его частью. При этом, на участках, которые определяются под объекты, мы задаем конкретные рамки для объектов. Иначе говоря, у нас есть список типов и каждый из них, может содержать несколько префабов. Что облегчает группировку и возможность установки объектов, в одно и тоже место.

В папке Resources проекта, создадим папку Market, а в ней нужно создать такие, имена которых соответствуют списку:

public enum MarketEnum
{
	Type_1,
	Type_2,
	Type_3
}

Простой игровой магазин (локальный)

Не забываем, что при изменении/создании элементов списка, нужно и переименовать вложенные папки.

Префабы, которые будут в этих папках, должны быть с коллайдером, при этом он должен перекрывать весь объект/модель. Или по крайней мере, коллайдер нужно разместить внизу модели, как подложку, потому что она необходима для измерения дистанции и правильного позиционирования. Еще важно, для префабов нашего магазина, создать отдельный слой.

Теперь, создадим пустой объект и вешаем:

using UnityEngine;
using System.Collections;

public class MarketComponent : MonoBehaviour {

	[SerializeField] private MarketEnum type;
	[SerializeField] private GameObject current; // по умолчанию можно указать свой объект, например, это старый дом, а после покупки он будет заменен на другой

	public GameObject Current
	{
		get{ return current; }
	}

	public MarketEnum Type
	{
		get{ return type; }
	}

	public void Initialize(GameObject obj)
	{
		if(obj == null) return;

		Destroy(current);

		Vector3 position = transform.position + new Vector3(0, 100, 0);
		current = Instantiate(obj, position, Quaternion.identity) as GameObject;
		current.name = obj.name;

		float distance = 0;
		RaycastHit hit;
		if(Physics.Linecast(transform.position, position, out hit, MarketManager.Use.Layers))
		{
			distance = hit.distance;
		}

		current.transform.position = new Vector3(position.x, current.transform.position.y - distance, position.z);
	}

	void OnDrawGizmos()
	{
		Color color = Color.blue;
		color.a = 0.5f;
		Gizmos.color = color;
		Gizmos.DrawCube(transform.position, new Vector3(1, 0.1f, 1));
	}
}

Простой игровой магазин (локальный)

Эту точку мы ставим там, где хотим создавать объект. Стоит обратить внимание, что нижняя часть объекта будет в текущей позиции. Если, например, нам нужно немного утопить какое-нибудь строение в грунт, то данную точку следует сдвинуть на нужную глубину.

Создадим основной класс, отвечающий за управление и сохранение:

using UnityEngine;
using System.Collections;
using System.IO;

public class MarketManager : MonoBehaviour {

	[SerializeField] private LayerMask layerMask; // выбираем слои, которые установлены на наших префабах
	[SerializeField] private string fileName = "Market.data"; // куда будем записывать данные
	[SerializeField] private string marketPath = "Market"; // родительская папка в Resources
	[SerializeField] private MarketComponent[] marketList; // указываем точки, для купленных объектов

	private static MarketManager _use;

	public static MarketManager Use
	{
		get{ return _use; }
	}

	public LayerMask Layers
	{
		get{ return layerMask; }
	}

	void Awake()
	{
		_use = this;
		Load();
	}

	internal T ParseEnum<T>(string value) // парсим string в enum
	{
		try
		{
			var parse = System.Enum.Parse(typeof(T), value, true);
			if(parse != null) return (T) parse;
		}
		catch 
		{
			Debug.Log(typeof(T) + " --> элемент списка не найден: " + value);
		}

		return default(T);
	}

	string DataPath()
	{
		return Application.persistentDataPath + "/" + fileName;
	}

	public void Save()
	{
		StreamWriter writer = new StreamWriter(DataPath());

		foreach(MarketComponent comp in marketList)
		{
			if(comp.Current != null)
			{
				writer.WriteLine(comp.Current.name + "|" + comp.Type);
			}
		}

		writer.Close();

		Debug.Log(this + " --> сохранение в файл: " + DataPath());
	}

	void Load()
	{
		if(!File.Exists(DataPath()))
		{
			return;
		}

		StreamReader reader = new StreamReader(DataPath());

		while(!reader.EndOfStream)
		{
			string[] text = reader.ReadLine().Split(new char[]{'|'});

			if(text.Length == 2)
			{
				Required(text[0], ParseEnum<MarketEnum>(text[1]));
			}
		}

		reader.Close();
	}

	public void Required(string objName, MarketEnum type)
	{
		if(objName.Trim() == string.Empty) return;

		string path = marketPath + "/" + type + "/" + objName;
		GameObject prefab = null;

		foreach(MarketComponent comp in marketList)
		{
			if(comp.Type == type)
			{
				prefab = Resources.Load<GameObject>(path);

				if(prefab == null)
				{
					Debug.Log(this + " --> запрашиваемый объект не найден: " + path + ".prefab");
					return;
				}

				comp.Initialize(prefab);
			}
		}
	}
}

Загрузка происходит на старте сцены, а сохранение необходимо вызывать.

Класс для UI кнопок:

using UnityEngine;
using System.Collections;

public class MarketButtonUI : MonoBehaviour {

	[SerializeField] private string prefabName;
	[SerializeField] private MarketEnum type;
	[SerializeField] private int price;

	public void MarketButton()
	{
		if(PlayerMoney.Use.Buy(price))
		{
			MarketManager.Use.Required(prefabName, type);	
		}
	}
}

Настройки покупки. Имя объекта, его тип и цена.

Еще небольшой скрипт, кошелек игрока:

using UnityEngine;
using UnityEngine.UI;
using System.Collections;

public class PlayerMoney : MonoBehaviour {

	[SerializeField] private Text info;
	[SerializeField] private int defaultValue = 1000;
	private int money;

	private static PlayerMoney _use;

	public static PlayerMoney Use
	{
		get{ return _use; }
	}

	public int Value
	{
		get{ return money; }
	}

	void Awake()
	{
		_use = this;
		money = defaultValue;
		ToScreen();
	}

	void ToScreen()
	{
		info.text = "Money: " + money;
	}

	public bool Buy(int val)
	{
		int j = money - val;

		if(j > 0)
		{
			money -= val;
			ToScreen();
			return true;
		}

		Debug.Log(this + " --> недостаточно средств, нужно еще: " + Mathf.Abs(j) + " RUB");
		return false;
	}
}

Сохранение для кошелька нету, так как это просто для примера. Берем нужные функции и встраиваем их в свой проект.

Скачать демо проект:

У вас нет доступа!
Тестировалось на: Unity 5.4.1

Комментариев 1

Офлайн
Однако неплохо,даже очень офигительно. Если знать хотя бы азы программирования и иметь логику,то можно добавить кучу полезных функций,но всё же.Мне как новичку не сильно понятно одну вещь,как устроить всё по примеру ->Купил->Получил в инвентарь-> поместил на необходимую местность,но это уже мои проблемы....
Информация
Посетители, находящиеся в группе Гости, не могут оставлять комментарии к данной публикации.
  • Яндекс.Метрика