Кодовый замок [2D UI]

Понадобился скрипт с возможностью автоматического создания панели кнопок и программного добавления событий кнопкам, чтобы не заморачиваться ручной настройкой и иметь возможность пробовать различные параметры, не переделывая всё с нуля. Мелочь, но если кому надо, разбираем. В текущем виде, кодовый замок, это набор кнопок и поле ввода текста, ничего более. Визуальное оформление каждый делает на своё усмотрение. Набор кнопок стандартный: цифры, сброс и ввод. Плюс есть несколько сообщений, например, на случай ввода неверного пароля или же наоборот. Если пароль верен, предусмотрена пара массивов для активации и деактивации, указанных объектов.

Кодовый замок [2D UI]

Стоит отметить что замок сделан на базе UI, подойдет для игр типа квеста или любой другой, где нужно вынести замок на экран, как картинку.

Делаем заготовки. Добавляем на сцену Canvas. Далее к нему:
Добавляем пустой RectTransform в котором будут собраны все кнопки, переименуем в Panel.
Добавляем Button настраиваем визуально как нужно.
Добавляем InputField, снимаем галочку Interactable, так как ввод нам нужен только с кнопок.

По сути замок готов, всё остальное оформление по вкусу.



Вешаем на Canvas скрипт CodeLock:

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

public class CodeLock : MonoBehaviour {

	[Header("General")]
	public bool unlock; // переходит в true если замок открыт
	public InputField _InputField; // поле ввода текста
	public string password = "123"; // текущий пароль замка
	public GameObject[] objectsOn; // массив объектов, которые надо активировать
	public GameObject[] objectsOff; // массив объектов, которые надо деактивировать
	[Header("Messages")]
	public string error = "ОШИБКА";
	public Color errorColor = Color.red;
	public string success = "ПАРОЛЬ ПРИНЯТ";
	public Color successColor = Color.green;
	public string defaultText = "ВВЕДИТЕ ПАРОЛЬ";
	public Color defaultColor = Color.black;
	[Header("Buttons")]
	public float offset = 10; // расстояние между кнопками
	public RectTransform button; // объект UI Button 
	public RectTransform panel; // пустой RectTransform, относительно центра которого, будет построена сетка
	public bool buildButtons; // создать кнопки?
	public RectTransform[] allButtons;
	
	void Start() 
	{
		unlock = false;
		_InputField.interactable = false;
		_InputField.characterLimit = password.Length;
		ResetPass();
		if(buildButtons) BuildGrid(); else SetButton();
	}

	void SetButton() // добавление событий для кнопок
	{
		int i = 1;
		for(int j = 0; j < allButtons.Length; j++)
		{
			switch(i)
			{
			case 10:
				allButtons[j].GetComponentInChildren<Text>().text = "R";
				allButtons[j].GetComponent<Button>().onclick.AddListener(() => {ResetPass();});
				break;
			case 11:
				allButtons[j].GetComponentInChildren<Text>().text = "0";
				allButtons[j].GetComponent<Button>().onclick.AddListener(() => {AddKeyPass("0");});
				break;
			case 12:
				allButtons[j].GetComponentInChildren<Text>().text = "E";
				allButtons[j].GetComponent<Button>().onclick.AddListener(() => {EnterPass();});
				break;
			default:
				string number = i.ToString();
				allButtons[j].GetComponentInChildren<Text>().text = number;
				allButtons[j].GetComponent<Button>().onclick.AddListener(() => {AddKeyPass(number);});
				break;
			}
			i++;
		}
	}
	
	void BuildGrid() // создание кнопок
	{
		float sizeX = button.sizeDelta.x + offset;
		float sizeY = button.sizeDelta.y + offset;
		float posX = -sizeX * 3 / 2 - sizeX / 2;
		float posY = Mathf.Abs(posX) - sizeY / 2;
		float Xreset = posX;
		int i = 0;
		allButtons = new RectTransform[12];
		for(int y = 0; y < 4; y++)
		{
			posY -= sizeY;
			for(int x = 0; x < 3; x++)
			{
				posX += sizeX;
				allButtons[i] = Instantiate(button) as RectTransform;
				allButtons[i].SetParent(panel);
				allButtons[i].anchoredPosition = new Vector2(posX, posY);
				allButtons[i].gameObject.name = "Button_ID_" + i;
				i++;
			}
			posX = Xreset;
		}
		SetButton();
		button.gameObject.SetActive(false);
	}
	
	public void AddKeyPass(string key) 
	{
		if(_InputField.text.Length < password.Length)
		{
			_InputField.text += key;
		}
	}

	void ClearText()
	{
		_InputField.text = string.Empty;
	}
	
	public void EnterPass() 
	{
		if(_InputField.text == password)
		{
			foreach(GameObject obj in objectsOn)
			{
				obj.SetActive(true);
			}
			foreach(GameObject obj in objectsOff)
			{
				obj.SetActive(false);
			}

			foreach(RectTransform tr in allButtons)
			{
				// делаем кнопки неактивными, если пароль принят
				tr.GetComponent<Button>().interactable = false;
			}

			unlock = true;
			ClearText();
			_InputField.placeholder.GetComponent<Text>().text = success;
			_InputField.placeholder.GetComponent<Text>().color = successColor;
		}
		else
		{
			ClearText();
			_InputField.placeholder.GetComponent<Text>().text = error;
			_InputField.placeholder.GetComponent<Text>().color = errorColor;
		}
	}
	
	public void ResetPass() 
	{
		ClearText();
		_InputField.placeholder.GetComponent<Text>().text = defaultText;
		_InputField.placeholder.GetComponent<Text>().color = defaultColor;
	}
}

Заполняем все переменные и тестируем.

Чтобы создать набор кнопок ставим галочку Build Buttons, запускаем сцену и далее ручками размещаем панель с кнопками как нужно, и перетаскиваем Canvas в папку с префабами. Готово. Потом в этом префабе снимаем ранее установленную галочку, скрипт будет использовать уже созданный набор из массива, не создавая новый. Программное добавление событий Button.onclick сохраняется, тоесть ничего редактировать не придется. Фишка в том, что можно быстро создавать различные панели с кнопками, изменяя форму одной кнопки-заготовки и регулируя параметр Оffset.

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

Внимание! Посетители, находящиеся в группе Гости, не могут скачивать файлы.

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

Офлайн
Почему бы не написать расширение эдитора, вместо того что бы смешивать код? И не нужно будет канвас префабить, и лишнего кода в билде не будет
Офлайн
Iskroff 21 сентября 2019
А в чем прикол. Ничего не объяснено то толком на самом деле. Как поставить его на дверь или куда-нибудь там. Как сделать так чтобы разблокировался какой либо объект после его открытия.
Офлайн
Light 21 сентября 2019
Iskroff, материалы предоставляются как образцы, тех или иных решений, чтобы было с чего начать и куда двигаться дальше. Некоторые можно сразу использовать в игре, а для некоторых надо немного поработать головой.
Информация
Посетители, находящиеся в группе Гости, не могут оставлять комментарии к данной публикации.
  • Яндекс.Метрика