Диалоги для простоты мы будем отображать в небольшом окне над лягушкой, для чего будем использовать Canvas, который на этот раз настроим так, чтобы его элементы отображались в мировом пространстве прямо над головой Jambi, а не накладывались на весь экран.
Нам потребуется новый холст, так как его настройки будут отличаться от того холста, который у нас есть сейчас проекте.
Выберите в окне иерархии объект Jambi и нажмите кнопку «+» вверху или кликните по Jambi правой кнопкой мыши, после чего выберите пункт UI > Canvas. У нас появится дочерний игровой объект Canvas для Jambi:
В настоящее время холст накладывается на экран. Измените свойство Render Mode на World Space.
Сейчас наш Canvas имеет слишком большие размеры. Размер холста указан в пикселях, если посмотреть, то значения ширины и высоты больше тысячи пикселей. Вы можете изменить эти значения, чтобы уменьшить размеры холста - например, установить ширину 3 единицы и высоту 2 единицы, но это затруднит создание пользовательского интерфейса, поскольку холст станет очень маленького размера и разместить на нем элементы интерфейса будет очень сложно. Поэтому ширину и высоту мы уменьшим до значений 300 и 200.
Вместо этого нужно уменьшить масштаб Canvas, тогда значения ширины и высоты останутся неизменными, но размер сцены уменьшится.
Установите значения для Rect Transform:
- Pos.X и Pos.Y на 0
- Width 300 и Height 200
- Scale на 0.01 по X , Y и Z
Обратите внимание, что прямоугольник холста станет небольшим и разместится рядом с лягушкой. Переместите его так, чтобы он оказался над персонажем лягушки при помощи мышки.
Теперь добавим изображение - выберите в окне иерархии Canvas, нажмите правую кнопку мыши или кнопку «+» вверху и выберите UI > Image. В окне проекта перейдите в папку Assets/Art/Sprites/UI и перетащите спрайт UIDialogBox в поле «Source Image» созданного изображения. Если изображение не появилось на сцене, увеличьте параметр Order In Layer у объекта Canvas.
Увеличьте изображение, чтобы заполнить холст полностью, выбрав в свойстве Rect Transform нижний правый вариант, при этом удерживая нажатой клавишу Alt:
Теперь в окно диалога необходимо добавить поле для отображения текста. Щелкните правой кнопкой мыши по объекту изображения в иерархии и выберите UI > Text > TextMeshPro. Появится следующее диалоговое окно:
Нажмите «Import TMP Essential». Когда импорт завершится и эта кнопка станет неактивной, окно можно закрыть.
Как и ранее для изображения, выберите в свойстве Rect Transform нижний правый вариант, при этом удерживая нажатой клавишу Alt, чтобы расширить текст до полного размера родительского изображения.
Затем уменьшите размеры желтых границ (это границы текста) при помощи маленьких квадратиков на них:
Теперь в инспекторе можно написать свой текст, изменить стиль текста, его цвет и др. Например вот так:
Осталось правильно отображать и убирать окно диалога.
Для начала нам нужно скрыть созданный Canvas диалога. Выберите его в окне иерархии и снимите флажок в верхней части инспектора:
Обратит внимание, что диалог пропадет со сцены. С помощью этого флажка вы можете включать или наоборот убирать игровые объекты со сцены. Это не эквивалентно методу Destroy, так как объекты не пропадают, а просто становятся невидимыми и не участвуют в процессе игры.
Выберите Jambi и добавьте ему новый скрипт с именем NonPlayerCharacter.
В скрипте создайте следующие переменные:
- публичная переменная displayPeriod типа float со значением по умолчанию равным 4, которая будет хранить продолжительность отображения диалогового окна в секундах;
- публичная переменная dialogBox типа GameObject, в котором будет храниться игровой объект Canvas, таким образом мы сможем включать и выключать его прямо в скрипте.
- непубличная переменная timerDisplay типа float, которая будет хранить значение в секундах, сколько осталось до выключения окна диалога.
public float displayPeriod= 4.0f;
public GameObject dialogBox;
float timerDisplay;
В методе Start дублируем выключение диалогового окна и задаем значение timerDisplay равное -1:
void Start()
{
dialogBox.SetActive(false);
timerDisplay = -1.0f;
}
В методе Update обновления проверьте значение переменной timerDisplay. Так как в ней хранится значение сколько осталось до выключения диалога, то если значение этой переменной больше нуля, это значит, что диалог в данный момент был включен. В методе Start мы задали значение этой переменной -1, значит диалог выключен ,если значение меньше нуля.
Если диалог включен, то нужно уменьшить время до выключения timerDisplay на время, прошедшее с предыдущего кадра - Time.deltaTime.
Затем нужно проверить, достиг ли timerDisplay нуля, что означает, что пришло время снова скрыть диалоговое окно, поэтому нужно просто отключить диалоговое окно:
void Update()
{
if (timerDisplay >= 0)
{
timerDisplay -= Time.deltaTime;
if (timerDisplay < 0)
{
dialogBox.SetActive(false);
}
}
}
И осталось общедоступную функцию DisplayDialog, которую будет вызывать скрипт RubyController, когда Ruby столкнется с лягушкой. Этот метод отобразит диалоговое окно и инициализирует значение timeDisplay значением displayPeriod, чтобы начался обратный отсчет времени отображения диалога:
public void DisplayDialog()
{
timerDisplay = displayPeriod;
dialogBox.SetActive(true);
}
Проверьте скрипт и сохраните его:
Теперь откроем скрипт RubyController и заменим Debug.Log, который мы написали для Raycast, этим кодом:
if (hit.collider != null)
{
NonPlayerCharacter character = hit.collider.GetComponent<NonPlayerCharacter>();
if (character != null)
{
character.DisplayDialog();
}
}
Этот код должен быть вам уже понятен. В условии попадания луча в коллайдер мы ищем скрипт NonPlayerCharacter на объекте этого коллайдера. Если этот сценарий существует на этом объекте, то вызывается метод отображения диалогового окна.
Проверьте скрипт и сохраните его:
Не забудьте назначить в свойство dialogBox скрипта объекта Jambi объект Canvas:
Запустите игру, попробуйте еще раз заставить Ruby поговорить с Jambi. На этот раз диалоговое окно появится, а затем исчезнет через четыре секунды.