본문 바로가기

Unity 공부시작/Unity2D 게임 및 기능구현

유니티2D :: 대화 이벤트 구현 연습

https://www.youtube.com/watch?v=znhOiyMDe9g

위의 블로그를 보고 구현하였습니다.




쓰인 애셋들은 모두 유니티 에셋 스토어에서 무료로 받은 에셋들입니다.


캐릭터 sprite, 캐릭터의 말들이 쓰여질 Text, Text의 바탕이 될 Window 세 가지로 이루어져 있습니다.


using System.Collections; using System.Collections.Generic; using UnityEngine; [System.Serializable] public class Dialogue { [TextArea(1,2)] public string[] sentences; public Sprite[] sprites; public Sprite[] dialogueWindow; }

다이어로그가 저장되는 클래스로 위와 같이 생성 시 유니티 엔진에서 size를 지정해줄 수 있고 이 후에 문장들을 써 넣을 수 있습니다.


= System.Serializable  :  유니티 엔진의 인스펙터 뷰에 노출시키는 키워드 


= 단, 클래스가 아무것도 상속하지 않고 있을 때 사용 가능



< DialogueManager Class >

// 다이어로그 시작 // public void ShowDialogue(Dialogue dialogue) { // 리스트 채우기 // for(int i=0; i<dialogue.sentences.Length; ++i) { listSentences.Add(dialogue.sentences[i]); listSprites.Add(dialogue.sprites[i]); listWindows.Add(dialogue.dialogueWindow[i]); } // 캐릭터 및 대화창이 나오도록 함 aniSprite.SetBool("Appear", true); aniWindow.SetBool("Appear", true); // 다이어로그를 보여주는 코루틴 실행 StartCoroutine(StartDialogueCoroutine()); }

ShowDialogue() 를 실행시켜주면 코루틴이 실행되면서 대화 이벤트가 시작됩니다.


IEnumerator StartDialogueCoroutine() { talking = true; text.text = ""; // 대화가 두 번 이상 진행된 경우 if(count > 0) { // 윈도우가 다른 경우 // if (listWindows[count - 1] != listWindows[count]) { aniWindow.SetBool("Change", true); aniWindow.SetBool("Appear", false); yield return new WaitForSeconds(0.01f); // 출력할 스프라이트, 윈도우 저장 // srSprite.sprite = listSprites[count]; srWindow.sprite = listWindows[count]; aniWindow.SetBool("Appear", true); aniWindow.SetBool("Change", false); } // 윈도우가 같은 경우 // else { // 윈도우가 같고 스프라이트가 다른 경우 // if (listSprites[count] != listSprites[count]) { // 스프라이트 변경 aniSprite.SetBool("Change", true); yield return new WaitForSeconds(0.1f); srSprite.sprite = listSprites[count]; aniSprite.SetBool("Change", false); } // 윈도우, 스프라이트 모두 다 동일한 경우 // else { yield return new WaitForSeconds(0.05f); } } } // count가 0인 경우 ( 첫 이미지인 경우 ) else { srWindow.sprite = listWindows[count]; srSprite.sprite = listSprites[count]; } // 텍스트 출력 // for(int i=0; i<listSentences[count].Length; ++i) { text.text += listSentences[count][i]; // 한글자씩 출력 yield return new WaitForSeconds(0.01f); } }


 첫 대화가 시작된 경우에는  ( count가 0인 경우 ) 리스트에 저장된 첫 스프라이트와 윈도우, 텍스트를 출력해줍니다.


단 두 번째 대화부터는 그 전에 사용된 스프라이트와 윈도우가 같은 지 검사한 후에 애니메이터에 파라미터를 전달해주어야 합니다.


같을 경우에는 변경할 필요가 없지만 다른 경우에는 스프라이트와 윈도우를 갱신해주어야 하기 때문입니다.



위의 과정을 거치고 나면 스프라이트와 윈도우를 저장할 변수에 각각 출력 예정인 것들을 넣어주고 마지막 텍스트 출력을 해 줍니다.


텍스트 출력의 경우 for문으로 구현하여 한 글자씩 나오도록 할 수 있습니다.


public void ExitDialogue() { talking = false; //// 초기화 //// count = 0; text.text = ""; // 리스트 초기화 // listSentences.Clear(); listWindows.Clear(); listSprites.Clear(); // 애니메이터 초기화 // aniSprite.SetBool("Appear", false); aniWindow.SetBool("Appear", false); }

위는 다이어로그가 모두 종료되었을 때 실행되는 함수입니다. 사용한 변수들을 모두 초기화 해줍니다.


private void Update() { if(talking) { // 대화를 읽음 if (Input.GetKeyDown(KeyCode.Space)) { ++count; // 모든 대화를 읽은 경우 if (count == listSentences.Count) { // 모든 코루틴 종료 StopAllCoroutines(); ExitDialogue(); } else { StopAllCoroutines(); StartCoroutine(StartDialogueCoroutine()); } } } }

Space를 누를 시 대화를 읽었다는 것이고 다음 대화를 출력해주어야 하므로 count를 증가시켜 줍니다.


모든 대화를 읽고 나면 문장의 개수와 count가 같게 되는데 이 때 모든 코루틴을 종료시키고 Dialogue를 종료시킵니다.


아직 대화를 모두 읽지 않은 상태인 경우에도 StopAllCoroutines()를 실행하는데 이는 사용자가 대화를 읽는 키 space를 연타하는 경우 


코루틴이 중복 실행되는 것을 막기 위함입니다.