Делаем журнал сообщений

Фактически уже готовый проект для использования в игре, осталось только оформить визуально по вкусу и в принципе всё. Работает следующим образом. Есть отдельный скрипт, в который мы записываем массив сообщений игры и массив с заголовками, так же в этом скрипите мы выбираем язык сообщений. Далее, на игровой карте, в нужных местах расставляем триггеры, каждый триггер хранит ссылку на скрипт журнала и номер индекса массива с сообщениями, который мы хотим добавить в журнал. Задача самого журнала, составлять список на основе массива заголовков и по запросу вызывать соответствующее сообщение.

Стоит отметить что новые сообщения, добавляются вверх списка, как бы сортировка по дате.

Скрипт JournalText, в котором будет храниться весь текст:

using UnityEngine;
using System.Collections;

public class JournalText : MonoBehaviour {

	public enum Lang {English = 0, Russian = 1}; // список языков
	public Lang language = Lang.Russian; // выбор текущего языка

	private static string[] text;
	private static string[] title;

	void Awake()
	{
		SetLang();
	}

	public void SetLang() // функция переключения на выбранный язык
	{
		switch(language)
		{
		case Lang.English:
			text = new string[]{
				"text 0",
				"text 1",
				"text 2",
				"text 3",
				"text 4",
				"text 5"
			};
			title = new string[]{
				"title 0",
				"title 1",
				"title 2",
				"title 3",
				"title 4",
				"title 5"
			};
			break;

		case Lang.Russian:
			text = new string[]{
				"текст 0",
				"текст 1",
				"текст 2",
				"текст 3",
				"текст 4",
				"текст 5"
			};
			title = new string[]{
				"заголовок 0",
				"заголовок 1",
				"заголовок 2",
				"заголовок 3",
				"заголовок 4",
				"заголовок 5"
			};
			break;
		}
	}

	public static string[] GetText
	{
		get{ return text; }
	}

	public static string[] GetTitle
	{
		get{ return title; }
	}
}

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

Далее. Скрипт журнала PlayerJournal, который мы добавляем на сцену:

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

[RequireComponent(typeof(JournalText))]

public class PlayerJournal : MonoBehaviour {

	public KeyCode keyCode = KeyCode.J; // клавиша вызова журнала
	public RectTransform element; // стандартный UI Button элемент
	public ScrollRect scrollRect; // окошко для отображения списка сообщений
	public Text popup; // окно где будет показан текст сообщения
	public int offset = 20; // расстояние между элементами списка

	private Vector2 delta;
	private Vector2 e_Pos;
	private static bool _active;
	private int index;
	private List<RectTransform> buttons;
	private float tmp;

	public static bool isActive
	{
		get { return _active; }
	}

	void Start() 
	{
		buttons = new List<RectTransform>();
		_active = false;
		delta = element.sizeDelta;
		delta.y += offset;
		BuildWindow();

		element.gameObject.SetActive(false);
		scrollRect.gameObject.SetActive(false);
		popup.transform.parent.gameObject.SetActive(false);
	}

	void Lock()
	{
		_active = true;
		scrollRect.gameObject.SetActive(true);
	}
	
	void UnLock()
	{
		_active = false;
		scrollRect.gameObject.SetActive(false);
	}

	void Update() 
	{
		if(Input.GetKeyDown(keyCode) && !_active) Lock();
		else if(Input.GetKeyDown(keyCode) && _active) UnLock();
	}

	void SetPopup(int id)
	{
		popup.transform.parent.gameObject.SetActive(true);
		popup.text = JournalText.GetText[id];
	}

	void ButtonSetup(Button button, int value) 
	{
		button.onclick.AddListener(() => SetPopup(value));
	}

	public void AddToList(int id)
	{
		element.gameObject.SetActive(true);
		tmp = 0;
		index++;
		BuildWindow();
		foreach(RectTransform b in buttons)
		{
			b.anchoredPosition = new Vector2(e_Pos.x, e_Pos.y + tmp);
			tmp += delta.y;
		}
		BuildElement(id);
		element.gameObject.SetActive(false);
	}

	void BuildElement(int id)
	{
		RectTransform clone = Instantiate(element) as RectTransform;
		clone.SetParent(scrollRect.content);
		clone.localScale = Vector3.one;
		clone.anchoredPosition = new Vector2(e_Pos.x, e_Pos.y + tmp);
		clone.GetComponentInChildren<Text>().text = JournalText.GetTitle[id];
		ButtonSetup(clone.GetComponent<Button>(), id);
		buttons.Add(clone);
	}
	
	void BuildWindow()
	{
		float height = delta.y * index;
		scrollRect.content.sizeDelta = new Vector2(scrollRect.content.sizeDelta.x, height);
		scrollRect.content.anchoredPosition = Vector2.zero;
		e_Pos = new Vector2(0, delta.y / 2);
	}
}

Некоторые уточнения. Переменная element ссылается на обычную UI кнопку, которую каждый будет оформлять как угодно, единственное что для трансформа кнопки нужно установить пресет:

Делаем журнал сообщений

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

Для функций Lock и UnLock можно еще использовать остановку времени, типа пауза:

Time.timeScale = 1; // 0 - остановить время, 1 - нормальное течение

Пример добавления новых сообщений в журнал. Создаем объект триггер и С# скрипт с любым названием, код будет выглядеть следующим образом:

public PlayerJournal playerJournal; // ссылка на журнал
public int journalIndex; // номер элемента массива сообщения, которое должно быть добавлено в журнал

void OnTriggerEnter(Collider other)
{
	if(other.tag == "Player")
	{
		playerJournal.AddToList(journalIndex);
		Destroy(gameObject);
	}
}

Когда игрок заходит в триггер, происходит выполнение функции добавления сообщения по указанному ID то есть journalIndex. Затем, триггер уничтожается, чтобы не было повторных добавлений одинаковых сообщений.

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

У вас нет доступа!

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

Офлайн
Atanashi 24 июля 2016
Почему то при использовании скрипта персонаж передвигается слишком быстро и во время передвижения отсутствует управления мышью. Как можно исправить эту ошибку?
Офлайн
Light 24 июля 2016
Atanashi, тут нет ничего, что может влиять на движение персонажа. Проблема в чем-то другом.
Офлайн
Atanashi 25 июля 2016
Light,
Как испоьзовать скрипт на игрока? Я пробывал использовать скрипт но почему то скрипт не работал. Работает только если использовать на MainCamera.
Офлайн
Light 25 июля 2016
Atanashi, он работает с UI и триггерами, а не с игроком.
Офлайн
Atanashi 25 июля 2016
Light,
Когда добавляю на карту FPSController скрипт не работает. Не открывается журнал. Без FPSController работает без проблем.
Офлайн
Light 26 июля 2016
Atanashi, скрипт журнала надо вешать на пустой объект, как в демо показано.
Офлайн
Atanashi 26 июля 2016
Light,
Ну я так и делал. Но когда я добавляю на карту FPSController то все не работает. Скрипт JournalText и PlayerJournal все так же остаются на пустом объекте.
Офлайн
Light 26 июля 2016
Atanashi, что за FPSController? Конкретнее надо говорить.
Офлайн
Atanashi 26 июля 2016
Это и есть игрок. Из стандартных ассетов.
Офлайн
Light 26 июля 2016
Цитата: Atanashi
Это и есть игрок. Из стандартных ассетов.

Надо просто этому префабу поставить тег Player. Потому как в стандартном варианте там не установлен тег или слой объекта.
Офлайн
Atanashi 26 июля 2016
Light,
Спасибо теперь все работает.
Офлайн
Type `Button' does not contain a definition for `onclick' and no extension method `onclick' of type `Button' could be found (are you missing a using directive or an assembly reference?) вот такую ошибку кидает
Офлайн
Light 21 октября 2016
Карен Аракелов, это ошибка вызвана вмешательством со стороны движка сайта. Нужно качать прикрепленный оригинальный пакет.
Офлайн
Light,
я его и скачал

Карен Аракелов,
и находясь в вашей демке , пишет эту ошибку
Офлайн
Light 21 октября 2016
Карен Аракелов, заменить значит onclick на

onClick

или

OnClick
Информация
Посетители, находящиеся в группе Гости, не могут оставлять комментарии к данной публикации.
  • Яндекс.Метрика