Привет, это небольшой урок о реализации интерфейса системы диалогов в Unity3D. Отмечу, что в статье не будет описано построение базы данных диалогов. В статье речь идет только о интерфейсе.
Для удобства я создал проект с основными ассетами(2 спрайта + шрифт), для его открытия нужна версия Unity3D 4.3+. На основе этого проекта мы будем писать систему диалогов.
I. Откройте пустую сцену "Dev”. Создайте GameObject с именем "DialogueSystem” В него добавьте два объекта типа "GUITexture” Назначьте им текстуры, и соответственно переименуйте их в "Background” и "Pointer” Теперь нужно задать Pixel Inset текстурам. Для текстуры задника это:
Pixel Inset для указателя:
Не забудьте изменить расположение текстур на 0,0,0, а с указателя уберите галочку активности. Тексту дайте имя "Text”, поставьте размер 38 и шрифт из папки "Fonts”, по желанию измените надпись, ну и отрегулируйте позицию:
Теперь из окна "Game” можно наблюдать примерно такую картину:
Создайте пустой GameObject с именем "Answers”, и внутри добавьте три объекта типа "GUIText” (временно можно отключить объект Text, что бы не мешался) Точно так же настройте размер, шрифт, обязательно дайте смешное значение в поле текст. Отрегулируйте позицию всем трем текстам, что бы все было примерно как здесь:
Отключите Answers и включите Text. Сохраните сцену и проект(на всякий случай). II. Теперь по коду. Скачаем для начала iTween, с ним даже плохие ассеты могут показывать хорошую картинку, благодаря красивым анимациям.
Зайдите в Asset Stote, в поиск введите "iTween”
Импортируйте его в проект. В папке Scripts создайте скрипт DialogueEditor на языке C#. Откройте его и тут же добавьте туда этот кусок кода, так мы будет управлять нашими объектами: <div class="bbCodeBlock"><div class="bbCodeName" style="padding-left:5px;font-weight:bold;font-size:7pt">Код</div><div class="codeMessage" style="border:1px inset;max-height:200px;overflow:auto;height:expression(this.scrollHeight<5?this.style.height:scrollHeight>200?'200px':''+(this.scrollHeight+5)+'px');"> public GameObject pointer; public GameObject answers; public GameObject textBackground; public GameObject text; </div></div> Добавьте скрипт к объекту DialogueSystem. Поставьте каждому полю его соответствующее значение:
Дальше довольно много переменных: <div class="bbCodeBlock"><div class="bbCodeName" style="padding-left:5px;font-weight:bold;font-size:7pt">Код</div><div class="codeMessage" style="border:1px inset;max-height:200px;overflow:auto;height:expression(this.scrollHeight<5?this.style.height:scrollHeight>200?'200px':''+(this.scrollHeight+5)+'px');"> public float letterDelay = 0.06f; //Задержка в написании одной буквы для красивого эффекта public float transitionTime = 0.5f; //Время всех твинов
private string currentText; //Текущий текст private string testText = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " + "Sed sit amet interdum dui. Morbi et turpis ac tellus ullamcorper placerat. " + "Vivamus rutrum neque non luctus dapibus. " + "Nam elementum, nibh in lacinia ullamcorper, magna tortor pretium lorem, nec feugiat velit magna eget nisl. " + "Interdum et malesuada fames ac ante ipsum primis in faucibus. " + "Sed fringilla magna augue, vel fermentum turpis mattis eu."; //Любой текст, который будет форматироваться и изменяться в процессе. private List<string> testAnswers = new List<string> (); //Лист с тремя вариантами ответов private string formattedText; //Отформатированный текст для нашего окна private string nextText; //Отрезок оставшегося текста private bool tweenCompleted; //Любое действие можно будет совершить только если все анимации и твины закончены private bool answersMode; //Отвечам или читаем private int selectedAnswer = 0; //Выбранный на данный момент ответ private int maxLetters = 50; //Макс. кол-во букв private int maxLines = 3; //Макс. кол-во строчек </div></div> В начале документа добавьте импорт: "using System.Collections.Generic;” - это для использования "List” Код функции Reset (если уже не терпится все скопипастить, архив с проектом в конце статьи): <div class="bbCodeBlock"><div class="bbCodeName" style="padding-left:5px;font-weight:bold;font-size:7pt">Код</div><div class="codeMessage" style="border:1px inset;max-height:200px;overflow:auto;height:expression(this.scrollHeight<5?this.style.height:scrollHeight>200?'200px':''+(this.scrollHeight+5)+'px');"> void Reset (bool next = false) { text.SetActive (true); //Возвращаем все на свои места answersMode = false; tweenCompleted = false; text.guiText.text = ""; formattedText = ""; iTween.FadeFrom (textBackground, 0, next ? transitionTime/3 : transitionTime/2); //Небольшое ускорение анимации, если это не первое появление iTween.MoveFrom(textBackground,iTween.Hash("y",-1f,"time",next ? transitionTime/3 : transitionTime/2, "delay",0,"oncomplete","OnAppearingTweenComplete","onCompleteTarget", gameObject)); if (next) //Если есть продолжение текста, значит сейча выводим его { currentText = nextText; } else currentText = testText; } </div></div> Функция Start: <div class="bbCodeBlock"><div class="bbCodeName" style="padding-left:5px;font-weight:bold;font-size:7pt">Код</div><div class="codeMessage" style="border:1px inset;max-height:200px;overflow:auto;height:expression(this.scrollHeight<5?this.style.height:scrollHeight>200?'200px':''+(this.scrollHeight+5)+'px');"> void Start () { answersMode = false; testAnswers.Add ("i'm going to say hello"); testAnswers.Add ("i'm going to say shut up"); testAnswers.Add ("i'm going to say goodbye"); Reset (); } </div></div> Функция форматирования текста под нашу форму: <div class="bbCodeBlock"><div class="bbCodeName" style="padding-left:5px;font-weight:bold;font-size:7pt">Код</div><div class="codeMessage" style="border:1px inset;max-height:200px;overflow:auto;height:expression(this.scrollHeight<5?this.style.height:scrollHeight>200?'200px':''+(this.scrollHeight+5)+'px');"> public string FormatString ( string newText ) { string[] words = newText.Split(" "[0]); string result = ""; int numberOfLines = 1; int letterCounter = 0;
for( int index = 0; index < words.Length; index++) { string word = words[index].Trim(); if (index == 0) { result = words[0]; letterCounter+=words[0].Length; }
if (index > 0 ) { if (letterCounter + word.Length + 1 < maxLetters) { result += " " + word; letterCounter+=word.Length + 1; } else if (numberOfLines < maxLines) { result += "\n" + word; letterCounter = word.Length; numberOfLines += 1; nextText = ""; } else if (numberOfLines == maxLines) { nextText = currentText; nextText = nextText.Remove(0, result.Length); break; } } } return result; } </div></div> Тут же и функция "TypeText”, которая будет рисовать текст по одной букве: <div class="bbCodeBlock"><div class="bbCodeName" style="padding-left:5px;font-weight:bold;font-size:7pt">Код</div><div class="codeMessage" style="border:1px inset;max-height:200px;overflow:auto;height:expression(this.scrollHeight<5?this.style.height:scrollHeight>200?'200px':''+(this.scrollHeight+5)+'px');"> IEnumerator TypeText () { formattedText = FormatString (currentText); foreach (var letter in formattedText.ToCharArray()) { text.guiText.text += letter; yield return new WaitForSeconds(letterDelay); if (text.guiText.text == formattedText) { break; } } } </div></div> Функция Update: <div class="bbCodeBlock"><div class="bbCodeName" style="padding-left:5px;font-weight:bold;font-size:7pt">Код</div><div class="codeMessage" style="border:1px inset;max-height:200px;overflow:auto;height:expression(this.scrollHeight<5?this.style.height:scrollHeight>200?'200px':''+(this.scrollHeight+5)+'px');"> void Update () { if (tweenCompleted) { if (answersMode == false) { if (Input.GetKeyDown (KeyCode.Space)) { if (text.guiText.text != formattedText) { text.guiText.text = formattedText; } else if (text.guiText.text == formattedText && nextText != "") { Reset(true); } else if (text.guiText.text == formattedText && nextText == "") { ShowAnswers(); } } } else { if (Input.GetKeyDown (KeyCode.DownArrow)) { if (selectedAnswer + 1 < testAnswers.Count) { selectedAnswer++; } else if (selectedAnswer + 1 >= testAnswers.Count) { selectedAnswer = 0; } iTween.Stop(pointer); ResetPointer(); } if (Input.GetKeyDown (KeyCode.UpArrow)) { if (selectedAnswer + 1 > 1) { selectedAnswer--; } else if (selectedAnswer + 1 <= 1) { selectedAnswer = testAnswers.Count - 1; } iTween.Stop(pointer); ResetPointer(); } if (Input.GetKeyDown (KeyCode.Space)) { SelectAnswer(); } if (iTween.Count(pointer) == 0) StartPointerTween(); } } } </div></div> Мы почти готовы. Код связанный с ответами и анимацией указателя: <div class="bbCodeBlock"><div class="bbCodeName" style="padding-left:5px;font-weight:bold;font-size:7pt">Код</div><div class="codeMessage" style="border:1px inset;max-height:200px;overflow:auto;height:expression(this.scrollHeight<5?this.style.height:scrollHeight>200?'200px':''+(this.scrollHeight+5)+'px');"> private void ResetPointer () { pointer.transform.position = answers.GetComponentsInChildren<GUIText>() [selectedAnswer].transform.position; pointer.guiTexture.pixelInset = new Rect(((answers.GetComponentsInChildren<GUIText>() [selectedAnswer].transform.position.x/Screen.width) + answers.GetComponentsInChildren<GUIText>() [selectedAnswer].GetScreenRect().width) * 1.05f, pointer.guiTexture.pixelInset.y,pointer.guiTexture.pixelInset.width,pointer.guiTexture.pixelInset.height); }
Также если вы считаете, что данный материал мог быть интересен и полезен кому-то из ваших друзей, то вы бы могли посоветовать его, отправив сообщение на e-mail друга:
Игровые объявления и предложения:
Если вас заинтересовал материал «Создание интерфейса системы диалогов в Unity3D», и вы бы хотели прочесть что-то на эту же тему, то вы можете воспользоваться списком схожих материалов ниже. Данный список сформирован автоматически по тематическим меткам раздела.
Предлагаются такие схожие материалы:
Если вы ведёте свой блог, микроблог, либо участвуете в какой-то популярной социальной сети, то вы можете быстро поделиться данной заметкой со своими друзьями и посетителями.
отличная работа TideS. респект!!! ничем не отрицая ее ценности - просто дополнительная ссылка free система в ассет сторе (честно скажу - я тоже взялся писать нечто подобное - просто для развития навыков) удачи и реализации.