네오위즈

네오위즈 - 개발 일지 (9) - 다이얼로그 시스템(+CSVReader) 6/30 ~ 7/6

neeeeding 2025. 7. 10. 00:50

6/30 ~ 7/6

*해당 프로젝트에 기여한 날만 작성했습니다.

 

다이얼로그 시스템을 이전 개인 프로젝트에서 모두 가져온 후, 수정을 했습니다.

그리고 말풍선등 이전 개인 프로젝트에는 없던 것을 추가하고,

중력 파편 능력을 만들기 시작했습니다.

확실히 겹치는 일이 없으니 수월한 느낌입니다.

 

6/30


 

이전 개인 프로젝트의 다이얼로그를 (필요한 것만) 옮기는 일을 했습니다.

또 텍스트를 한 단어씩 출력하도록 하고 선택을 키보드 숫자를 눌러도 선택이 되도록 했습니다.

 

깃 데탑

 

나중에 수정을 많이 해서 다이얼로그 시스템에 대해서는 후술 하겠습니다.

 

7/1

 


 

대화 가능한 NPC와 불가능한 NPC를 구별하기 위해 말풍선을 만들었습니다. 또 회의를 하면서 중간 검사도 같이 했습니다.

 

말풍선

 

LookAt을 이용해 말풍선 UI가 늘 카메라를 바라보도록 했습니다.

말풍선 활성화 비활성화 관련해서는 7/2에 서술하겠습니다.

7/2

 


 

다이얼로그 시스템의 구조를 조금이라도 더 효율적으로 변경하고, 대화 가능 한 것이 기획 추가에 따라 섬과, NPC의 대화법이 다르기에 기존 것을 Entity로 하고, 이를 부모로 삼는 스크립트를 섬과 NPC로 나누었습니다.

또 발견한 오류도 수정했습니다.

말풍선도 수정했는데 가까우면 말풍선에 대화를, 멀면...... 을 출력하도록 변경했습니다.

또 액셀에서 말풍선 대화를 빼오도록 올바르게 변경했습니다.

 

구조를 굉장히 많이 바꾸긴 했는데 아직 모자라 보이긴 합니다...

 

관련 모든 스크립트...

 

벌써부터 막막하긴 한데, 대화가 가능한 DialogEntity에 대해 먼저 설명할겠습니다.

 

변수들

 

자신이 누구고 어떤 대화를 담는지

 

DialogEntitySO는 Entity의 이름, 대화 목록(CSV 목록)을 담는 SO입니다.

 

EntityName은 모든 Entity의 이름을 담은 enum입니다.

밑에 있는 CSV파일을 보면 아시게 될 텐데, 대화 목록에서는 말하고 있는 캐릭터의 이름이 me나 blue처럼 enum에서의 값과 같은 string값이 저장되어 있습니다. (나중에 enum.toString()로 비교합니다.)

또 Description는 애트리뷰트의 설명을 나타내는 메타데이터 (컴퓨터가 읽는 게 가능한 주석)인데 이를 사용한 이유는 지금 얘기하기엔 너무 이르기에 후술 하겠습니다.

 

DialogEntity 스크립트 앞 부분

 

우선 처음부터 대화가 가능한 게 아니니 모두 false 해줍니다.

 

그리고 OnDrawGizmos에서 탐지할 범위들을 그려줍니다.

이때 isChat은 상호작용키를 눌러 대화가 가능한 범위인지를 확인하고

isBubble는 말풍선을 띄우기 시작하는 범위입니다.

 

만약 isBubble &&! isChat이라면 말풍선에는...... 을 띄우고,

isBubble && isChat이라면 정상적인 말풍선 내용을 담습니다.

 

Update 내용은 상속받은 후 내용을 담기로 했습니다.

(감지)

 

DialogEntity 스크립트 뒷 부분

 

NextChapter에서는 다음 챕터로 넘어가도록 하는 게 원래 목적이었습니다.

그런데 작성하고 생각해 보니 이 대화형 NPC는 같은 내용을 반복하거나, 특정 조건을 만족할 때까지 반복해야 하는 경우가 클 거라 예상되었습니다.

 

*//chapter++; 더 자세히

더보기

만약 chapter++; 를 주석 처리 안 한다면 대화가 끝나고 다시 말을 걸면 다음 챕터로 넘어가는 식인데,

저는 반복을 원하니 chapter++; 만 주석하여 늘 대화가 초기화되는 식으로 변경했습니다.

 

실상 NextChapter은 다음 챕터가 아닌 대화 초기화 같은 역할이 되었지만

나중에 다시 조건을 해결했는지를 확인하고 챕터를 넘기도록 할 생각입니다.

 

테스트 CSV 파일(엑셀)

 

제가 다이얼로그 시스템을 CSV 파일을 이용해 만드는데요,

이 CSV 파일의 내용을 전부 딕셔너리에 옮겨서 사용합니다.

이때 가장 위에 즉 첫 줄이 Key 가 되고, 그 아래부터는 Value가 됩니다.

(다이얼로그_딕셔너리 [0][Text] = "어디 무급으로 일할 노예 없나..."가 됩니다.)

 

*Key에 대한 설명

더보기

Bubble는 챕터에 따른 말풍선입니다.

뭔 소리냐면 숫자가 있다면 이는 우선 Text의 값이 말풍선에 사용되는 말이라는 의미이고, 이 숫자는 챕터에 따른 말풍선이죠.

그러니까 대화의 진행사항이 2 챕터라면 위의 "어디 무급으로 일할 노예 없나"라는 말풍선 내용이 아니라 다른 내용이 담길 것입니다. (현재는 없습니다.)

Select는 선택지의 개수입니다. 빈칸이라면 선택지가 없다는 소리고 숫자가 있다면 해당 수만 큼 선택지가 있다는 소리입니다.

현재 최대 선택지는 3개입니다. 그리고 Select는 SelectText1 ~ 3과 세트입니다.

 

SelectText1 ~ 3은 선택지의 num을 의미합니다.

즉 "응 안돼. 일해"의 선택지로는 "ㅠㅠ 나는 거지야......"와 "감히 나에게 일하라고 해?!", "끄아아악... 갑자기 숨이..."가 됩니다.

 

Chapter는 대화의 진행 사항 중 가장 큰 대목으로 이야기가 한 번 실행할 때 한 흐름입니다.

Num은 Chapter의 세부 진행 사항으로 이야기의 순서입니다.

 

예시)

1 chapter

   - num 1
   - num 2
   - num 3...
2 chapter
   - num 1
   - num 2...

....

 

Text는 거창한 것 없이 대사 내용입니다.

(자세히 보셨다면 내용 중 뜬금없이 `가 찍혀 있는데 이는 CSV가 , 로 구분되기 때문에 `로 작성하여 나중에 출력할 때, 로 변환 합니다.)

 

Player는 말하고 있는 이를 말합니다.

이미지에 따르면 me는 주인공, owner는 주인입니다.

 

Item, Get, ItemCount는 다음 개발일지 때 사용 되긴 하나 간단히 설명하자면

Item는 얻거나 잃을 아이템, Get는 true면 얻고, false는 잃음을 알려주는, ItemCount는 얻거나 잃는 수

 

dialog의 값을 CSVReader.Read()를 통해 얻게 되는데, 

여기서 CSVReader는 에셋으로 제가 아주 살짝 손 본 버전입니다.

public class CSVReader
{
    static string SPLIT_RE = @",(?=(?:[^""]*""[^""]*"")*(?![^""]*""))";
    static string LINE_SPLIT_RE = @"\r\n|\n\r|\n|\r";
    static char[] TRIM_CHARS = { '\"' };

    public static List<Dictionary<string, object>> Read(TextAsset data)
    {
        var list = new List<Dictionary<string, object>>();
        //TextAsset data = Resources.Load(file) as TextAsset;

        var lines = Regex.Split(data.text, LINE_SPLIT_RE);

        if (lines.Length <= 1) return list;

        var header = Regex.Split(lines[0], SPLIT_RE);
        for (var i = 1; i < lines.Length; i++)
        {

            var values = Regex.Split(lines[i], SPLIT_RE);
            //if (values.Length == 0 || values[0] == "") continue;

            var entry = new Dictionary<string, object>();
            for (var j = 0; j < header.Length && j < values.Length; j++)
            {
                string value = values[j];
                value = value.TrimStart(TRIM_CHARS).TrimEnd(TRIM_CHARS).Replace("\\", "");
                object finalvalue = value;
                int n;
                float f;
                if (int.TryParse(value, out n))
                {
                    finalvalue = n;
                }
                else if (float.TryParse(value, out f))
                {
                    finalvalue = f;
                }
                entry[header[j]] = finalvalue;
            }
            list.Add(entry);
        }
        return list;
    }
}


*CSVReader 해설

더보기

TextAsset 형식을 매개변수로 받는데, 이 형식은 저의 경우 CSV 파일을 건네줍니다.

(CSV파일은 쉼표로 구분되는 파일을 말합니다.)

list는 List <Dictionary <string, object>>()인데, list [0]["Text"] 이런 식으로 사용되는 겁니다.
0은 CSV파일의 (Key 제외) 행 부분을 말하고,

"Text"는 CSV파일의 Key를 의미합니다.
[0]["Text"] 이 경우 "어디 무급으로 일할 노예 없나..." 이 값이 되는 거죠. 여기서 값은 Object 형식이 됩니다.

 

lines는 Regex.Split에 의해 data(CSV 파일)를 LINE_SPLIT_RE에 따라 배열로 나누어집니다.

@"\r\n|\n\r|\n|\r"는 전부 줄 바꿈에 대한 내용입니다.

즉 lines에는 행으로 나누어 저장됩니다.

 

또 header에서는 0번째 즉 Key가 될 부분을 , (단 " " 안에 있는 , 는 무시함)를 기준으로 나누어 저장합니다.

 

valus에는 list의 1번째부터 마지막까지 즉 0번째인 key를 건너뛰고  , (단 " " 안에 있는 , 는 무시함)를 기준으로 나누어 저장합니다.

 

entry는 header가 키고 [n][header]에 해당하는 값을 value로 가져서 list에 넣어주게 됩니다.

(계속 사용)

 

반복문을 통해 header 즉 key를 전부 돌게 됩니다.

돌면서 value에는 value [j]의 값을 넣고

value에서 "를 제거합니다.

그리고 value를 object로 저장한 후

그대로로 유지하거나 int 나 float로 형변환을 해주고 저장하게 됩니다.


사실 제 경우 object로 하여 형변환을 할 필요 없이 string로 유지해도 상관없긴 하나

원본 CSVReader에서는 object로 해두었기에 굳이 바꾸지는 않았습니다.

 

이를 반복하며 list가 채워집니다.

모든 반복이 끝나면 list를 return 합니다.

 

즉 CSVReader.Read()를 하면 리스트의 인덱스가 곧 행(+1)이고, key가 1열의 값인 

 List <Dictionary <string, object>> 를 retrun 하게 됩니다.

 

BubbleWord 같은 경우 아까 앞에서 서술했듯

*서술한 내용

더보기

만약 isBubble &&! isChat이라면 말풍선에는...... 을 띄우고,

isBubble && isChat이라면 정상적인 말풍선 내용을 담습니다.

말풍선 보여주는데, 멀면...... 을, 가까우면 대사를 띄어줍니다.

 

대사는 어떻게 정하냐면

먼저 이 다이얼로그 딕셔너리 (dialog)의 Bubble를 살핍니다.

숫자가 있다면 그 숫자를 지금 챕터와 비교를 하고, 같을 때(Text의 내용이) 말풍선에 출력할 문장으로 정해지게 됩니다.

 

DialogEntity 스크립트 중간 부분

 

CurrentDialog는 현재 이 entity의 dialog의 진행 사항 즉 챕터와 넘버를 넘겨줍니다.

 

nextDialog는 대화 중일 때마다 다음으로 넘어갈 때 호출되어 넘버를 갱신해 줍니다.

이를 하는 이유는 이 스크립트를 가져온 이전 프로젝트에서는 대화 도중 게임을 종료했을 경우

다시 실행했을 때 이어서 대화를 하도록 하기 위해서 해당 메서드를 호출합니다.

 

DoChat는 매개변수에 맞게 doChat의 값을 바꿔줍니다.

사실 지금 보니 왜 저렇게 만들었나 싶네요...

 

DoDialog는 대화를 실행하게 해주는 메서드로 DialogEntity를 상속하는 클래스에서 실행하고 있습니다.

 

말풍선 보여주는 캐릭터 형식

 

위의 클래스는 이전까지 설명하던 DialogEntity를 상속받고 있는 클래스입니다.

(Character는 말풍선을 보여주는 대화 가능한 NPC를 위한 스크립트입니다.)

Update에서 대화 가능 범위와 말풍선 가능 범위를 감지하고, 이에 따라 둘 값(dialogCount, SpeechBubbleCount)중 하나라도 달라지면 OnCanDialog 액션을 실행합니다.

 

ShowSpeechBublble 스크립트

 

그럼 Show를 실행하게 되는데 show(== isBubble)에 따라 말풍선을 활성화, 비활성화하고

chat(== isChat)에 따라 대사를 출력하거나...... 를 출력합니다.

(BubbleWord에 대해서는 위에 서술했습니다.)

또 해당 말풍선을 그 캐릭터 위치로 옮겨서 엉뚱한 위치에서 보여주지 않도록 합니다.

 

DoDialog에서는 대화가 가능한 상태이고(isChat), F(임의 키)를 눌렀으며 대화 중이 아닌지 (! doChat)를

살피고 OnChat 액션, 즉 대화를 실행합니다.

 

대화 실행에 대해서는 조금 있다가 설명하겠습니다.

이렇게 대화 전 말풍선을 보여주는 Character 스크립트의 설명은 끝이 났습니다.

이제 DialogEntity를 상속하는 나머지 하나를 설명하겠습니다.

 

말풍선 없이 즉시 대화 하는 섬 형식

 

BlueIsland라고 되어있긴 하나 아마 섬 모두 이 스크립트를 사용할 거 같아서 이름은 수정될 것 같습니다.

*섬에 대해서

더보기

저희 게임은 주인공의 여정이 섬에서 진행되는데,

주인공은 특별해서 섬과 대화할 수 있다는 설정을 가지고 있습니다.

섬마다 인격을 가지고 있고 섬에게는 대표하는 색이 있습니다.

현재 작업하고 있는 섬은 파란 섬입니다.

 

이 스크립트는 Update에서 마찬가지로 범위를 체크하는데, 섬의 경우 말풍선을 출력하지 않고, 대화가능 범위가 될 때 그 즉시 대화를 합니다. 그렇기에 Character과 달리 F 등 상호작용 키 또한 없습니다.

 

이로써 대화가 가능한  DialogEntity(+ 상속하는 클래스들)에 대한 설명은 끝났고, 이제 대화에 대해 설명하겠습니다.

 

굉장한...

 

구조는 버리고 다 몰아넣어서 굉장히 긴데... 이에 대해선 나중에 분리시키도록 하겠습니다.

(지금도 코드 못 짜는데 더  했을 때 짠 거 복붙 + 추가 내용이라...)

 

변수들

 

Dialog 스크립트

 

혹시 앞전에 OnChat 액션에 대해 기억하시나요? 대화를 실행할 때 이 액션을 실행하게 됩니다.

Character의 경우 대호 가능할 때 F 상호작용 키를 눌렀을 때, 섬의 경우 대화 가능한 범위가 되면 즉시 대화를 실행합니다.

OnChat 액션이 실행되면 Chat를 호출하게 됩니다.

 

무 의미 메서드

 

대화를 초반 세팅

 

Chat는 DialogSetting를 실행합니다.

(이전에 Chat 더 내용이 있었는데 다 지우고 DialogSetting만 남게 되었습니다.)

 

isSet를 이용해 중복 세팅을 하지 않으려 했는데 지금 보니

 

....?

 

코드를 자면서 썼나 지금 겨우 몇 번 훑었다고 이상한 거 투성인지....

마저 설명하고 이 일지를 마무리 지은 후 싹 수정하고 다음 일지를 작성해야겠습니다;;

 

아무튼 그 후 텍스트를 비워줍니다.

그리고 DialogUI (대화 창)을 활성화하고 currentSO와 _currentDialogEntity를 갱신해 줍니다.

(currentSO는 대화하는 캐릭터를 의미하는데 이 이유는 캐릭터마다 가지고 있는 CSV파일이 다르기 때문입니다.)

 

DoChat으로 대화 중임을 알려주고 챕터와 넘버를 받아줍니다.

 

선택지 다 안 보이게

 

 

OffSelectText()로 선택지들을 다 꺼줍니다.

 

대화 세팅 (dialog, currentChat)

 

GetDialog를 통해 갱신된 캐릭터의 CSV파일을 얻고

 

*DialogType

더보기
DialogType 이넘

 

CSV파일을 바탕으로 Key 값들을 더 수월히 찾기 위해 DialogType enum을 만들어 줬습니다.

 

currentChat를 얻게 됩니다.

currentChat는 실제 CSV파일에서 챕터와 넘버가 올바른 배열로 예를 들자면

CSV 파일

 

Chapter : 2, Num : 3 이면 currentChat는 16이 됩니다. (1줄은 Key이므로)

Chapter : 1, Num : 2 => currentChat : 3

 

다시 DialogSetting로 돌아가서 DoChat를 실행합니다.

 

DoChat는 간단히 서술하자면 대화가 가능한지 살핀 후 대화할 텍스트를 얻고, 대화를 세팅 (이름 변경 등)하고

마무리로 Chapter와 Num을 다음으로 변경합니다.

 

Update
상호작용 시 실행


DoChat에 대해 더 자세히 설명하려면 먼저 ClickNext에 대해 설명하고 넘어가야 할 것 같습니다.

 

ClickNext는 대화 중 F(임의) 상호작용 키를 누르거나 마우스 좌 클릭 시 실행됩니다.

이는 대화를 진행하게 하며, 대화가 끝나면 (DoChat) 캐릭터의 챕터를 다음으로 변환 (코드 변경으로 인해 실제로는 처음으로 리셋시켜줍니다. 앞의 내용을 참고) 후 대화창을 비활성화, 대화하는 캐릭터도 비워줍니다.

 

DoChat 앞 부분

 

getOut는 대화를 할 수 있는지 즉 대화가 끝났는지를 확인합니다. (사실 필요 없긴 합니다.)

DialogSetting에서는 무조건 대화를 실행하니 반환값이 필요 없지만 ClickNext의 경우에는 이 반환 값을 통해 대화를 종료하게 됩니다. (true : 종료, false : 진행)

 

nCount는 현재 출력하고 있는 단어의 번째입니다.

nCount!= 0이 아니면 모두 출력하게 되는데 이는 nCount는 DoChat 전에 0으로 만들어줍니다.

그런데 0이 아니란 소리는 이전에 모든 대화를 출력하지 못하고 진행 중이었을 때 DoChat를 또다시 실행했다는 소리가 됩니다.

이때는 스킵 즉 모든 글자를 출력해 주는 것이죠.

그리고 저희 게임에서는 내용을 스킵하는 기능을 만들 생각이 없으니 모든 글자를 출력하고 바로 retrun를 통해 나오게 됩니다.

 

그 후 대화가 존재하는지를 확인합니다. 대화 자체가 currentChat +1(key 행) 값보다 작다면 말 그대로 모든 대화가 끝이라는 것이고 (현재 currentChat는 이전 값이 아닌 지금 대화를 보여주려는 CSV파일의 행입니다.)

지금의 CSV파일[currentChat]의 챕터와 넘버가 현재의 chapter, num 중 어느 하나라도 맞지 않다는 것은 오버가 되었다는 소리로 현재 chapter의 내용은 끝이 났다는 소리가 됩니다.

 

*chapter가 오버되는 과정(자세히)

더보기
CSV 파일

 

위의 엑셀 이미지를 참고하여 currentChat가 13 일 때는 chapter : 1, num : 12입니다.

num은 CSV파일에서 NextNum 값을 가지게 되는데 chapter : 1, num : 12의 NextNum은 12를 가지고 있습니다.

그 이유는 12가 챕터의 마지막 대화 이므로 다음이 없으니 12인 것입니다.

그러니 이다음에서는 여전히 chapter : 1, num : 12를 가지고 있는데 currentChat는 14가 되어 있을 것입니다. (자세한 건 후술)

그러나 CSV파일에서 살펴보면 currentChat : 14 이면 chapter : 2, num : 1입니다.

챕터도 넘버도 맞지 않게 되죠.

 

또 대화 자체가 끝나게 되는 이유도 비슷합니다.

current : 22이면 오버가 되죠. CSV파일은 key를 포함해서 22줄이 있고, current + 1은 23이니

22 < 23 됩니다. 즉 Dialog.Count < currentChat + 1을 성립 못하게 됩니다.

 

이 두 경우 chapter가 오버한 것이라 볼 수 있습니다.

 

대화가 존재하다면 getOut를 false로 바꿔줍니다.

 

말하는 이 이름 갱신

 

혹시 CSV파일에 Player칸을 안 써둘 경우를 우려해 먼저 chatPlayer에 currentSO (대화하는 캐릭터)를 넣어줬습니다.

chatPlayer는 말하고 있는 이를 나타내며 currentSO는 대화를 제공하는 (즉 플레이어가 상호작용한) 캐릭터를 말합니다.

allCharacter에는 모든 캐릭터들이 담겨 있습니다.

 

현재 chapter와 num에 해당하는 player와 같은지를 확인 후 넣어줬습니다.

 

DoChat 뒷 부분

 

대화 이름 세팅

 

그리고 아까 갱신해 준 말하는 이의 이름 또한 갱신해 줍니다.

Name <T> 매서드에서는 어트리뷰트 description를 가져와 줍니다.

 

혹시 EntityName에 대해 기억하시나요?

 

EntityName

 

여기서 Description를 사용하게 됩니다.

Name <T>에서는 (DescriptionAttribute) Attribute.GetCustomAttribute()를 통해 이 Description의 내용을 가져오게 됩니다.

즉 만약 Name(EntityName.me) 실행 시 "플레이어"를 얻게 됩니다.

 

특정 문자를 다른 문자로 변경

 

이렇게 이름까지 얻은 후 대사도 얻는데요, 얻은 대사를 IsExchangeText를 통해 특정 문자를 변경합니다.

IsExchangeText(대사, "`", ", ");

이는 대사에서 `가 포함된 모든 부분을 , 로 변환 합니다.

이게 필요한 이유는 대사는 CSV파일에서 가져온 것이고 CSV파일은 , 로 구분하기에 대사에서 , 를 포함할 수 없습니다.

(물론 " " 안의, 는 가능합니다. 앞에서의 CSVReader해설 참고)

그렇기에 저는 , 가 필요한 부분을 CSV파일에서 ` 로 표시하고 이를 스크립트에서 다시 변환하여 사용하고 있습니다.

 

스크립트 설명 하자면 먼저 바꿀 문자가 포함되어있는지 확인합니다.

포함되어 있다면 그 문자를 기준으로 쪼개어 배열로 저장합니다.

그리고 그 배열만큼 for 문을 돌면서(마지막은 제외) 그 배열의 문자와 바꿀 문자를 더해 줍니다.

(Split를 사용하면 쪼개는 것에 기준이 된 문자는 자동으로 없애주므로 그냥 더해줍니다.)

마지막으로 다 더해진 문장을 반환합니다.

 

다시 DoChat로 돌아와서 isTime를 true로 해줍니다.

 

Update

 

isTime이면 업데이트에서 시간을 재기 시작합니다.

이걸 만든 이유는 사실 코루틴 안 쓰려고 만든 겁니다.

코루틴 시간을 새면 yeild return new WaitForSecound(); 이걸 쓰는데 대사마다 new를 감당하기엔 부담스러워서 이 방법을 택하였습니다.

 

아무튼 isTime을 true로 하여 시간을 재기 시작하고 0.2초마다 OneOne를 실행합니다.

 

한글자 씩 출력

 

대사를 한 단어씩 나눕니다.

만약 이미 완벽한 대사를 출력하고 있다면 isTime를 false로 하고 빠져나옵니다.

(다음 단어를 출력할 필요가 없기 때문에)

nCount 가 1이라면 지금이 첫 실행이기 때문에 빈칸을 출력합니다.

아니라면 아까 단어로 이루어진 배열을 돌게 됩니다.

오직 nCount 수에 해당한 단어만 더해줍니다.

왜냐하면 이미 이전에 출력된 단어를 굳이 또 더해 줄 필요도 없으며 매번 모두 지우고 새로 더하는 짓은 할 필요가 없기 때문입니다.

*출력 순서

더보기

(빈칸)

이것은

이것은 네오위즈

이것은 네오위즈 개발

이것은 네오위즈 개발 일지입니다.

 

현재 출력 방식

 

그리고 만약 nCount가 j보다 큰 경우는 모든 단어를 출력한 경우인데요.

정확히는 모든 단어 + 빈칸 인 셈입니다. 그러므로 그냥 깔끔히 원래 대사로 변경해 줍니다.

마찬가지로 isTime도 false로 바꿔주고요.

 

이렇게 하여 대사를 단어 당 끊어서 0.2초마다 한 단어 씩 출력하게 됩니다.

 

다시 DoChat로 돌아가서 캐릭터의  SO의 넘버를 갱신해 줍니다.

 

DoChat 뒷 부분 (너무 위에 있는 관계로)

 

선택지 세팅

 

CSV파일

 

HaveSelect는 선택지를 가지고 있는지 확인하고 그 선택지들을 세팅해 줍니다.

 

CSV파일에서 Select부분이 비어있다면 선택지가 없다는 의미입니다.

Select에 입력된 수만큼이 선택지의 개수입니다. (최대 3개)

선택지 개수만큼 선택 UI를 세팅합니다.

선택 UI안의 text는 마찬가지로 Text의 값이며 SelectText1 ~ 3 은 선택지들의 Num을 의미합니다.

 

아이템 가지고 있는지

 

HaveItem은 아이템을 가지고 있는지 확인하고 얻거나 잃는 일을 합니다.

 

현재 이 스크립트는 7/11, 7/13에 작성 중이기에 지금 이 스크립트에서는 확인만 하고 있습니다.

 

다음은 NextNum이 비어있는지 확인 후 비어있다면 그대로 숫자를 가지고

안 비어있다면 그 NextNum 숫자를 얻게 됩니다.

정확히는 nextNum이 현재 currentNum과 같다면 1을 더하고 아니면 nextNum - currentNum을 더하게 됩니다.

(결국 nextNum == currentNum? currentNum + 1 : nextNum의 값이 되는 거죠.)

 

한마디로 num 갱신입니다.

 

후... DoChat를 한마디로 설명하자면 대화를 위해 선택 & 아이템을 확인하고 대화를 위해 세팅도 하고 num을 갱신까지 하는 메서드 인 셈입니다.

 

드디어 기나긴 대화 시스템이 끝났습니다...

 

동영상 서비스가 종료되어 해당 콘텐츠를 재생할 수 없습니다.

 

7/3

 


 

회의를 진행했습니다.

 

7/6

 


 

드디어 중력 파편 능력을 만들기 위해 해당 능력을 사용할 수 있는 오브젝트들에게 능력 사용을 위한 UI가 뜨도록 만들었습니다.

그러나 이미 수정한 곳에서 너무 얽히기도 했고, 대화 시스템에 의해 막대한 분량이 있는 관계로 이에 대해선 개발 일지 (10)에 서술하겠습니다.

 

*7/4,7/5는 진행 사항이 없습니다.

 

일지


 

이전 일지 > https://neeeeding.tistory.com/33

 

네오위즈 - 개발 일지 (8) - 진행 무 6/2 ~ 6/29

6/2 ~ 6/86/9 ~ 6/156/16 ~ 6/226/23 ~ 6/29*해당 프로젝트에 기여한 날만 작성했습니다. 유감스럽게도 게응 수업의 개인 프로젝트, 겜프 수업의 팀 프로젝트, 수행평가들, 지필 평가가 겹쳐서진행사항 없이

neeeeding.tistory.com

 

다음 일지 > https://neeeeding.tistory.com/35

 

네오위즈 개발 일지 (10) - 개발 일지 작성 & 중력 파편 능력 7/7 ~ 7/13

7/7 ~ 7/13*해당 프로젝트에 기여한 날만 작성했습니다. 중력 파편 능력을 구현하고 티스토리에서 개발 일지를 작성하기 시작했습니다.또 다이얼로그 시스템을 살짝 수정 했습니다. 7/7 선택한 물

neeeeding.tistory.com