딱히 언급해본적은 없는 것 같은데 작업 방향성은 알만툴을 기준으로 잡고있다.
알만툴을 사용한 프로젝트를 진행해보기도 했고,
유니티 타일맵을 사용해 비슷한 느낌의 탑다운 장르를 만들어보기도 했는데
알만툴의 경우 확장성이 너무 떨어진다는 단점이 있었다.
많은 고수분들이 여러 플러그인들을 만들어주시기도 했지만
필요한 만큼 개조해서 사용하기에는 자바스크립트라는 언어의 한계가 있었다.
그래서 확장성을 좀 쉽게 이뤄보기 위해 유니티를 사용해
알만툴과 비슷한 기능들을 만들어 보고 있다.
📝 구현한 내용
1. 씬(퀘스트?) 단위로 대사 출력
2. 선택지 기능을 비롯한 여러 흐름 제어 요소 추가
이전 글의 변수나 구조가 좀 지저분한것 같아서 많이 정리했다.
[System.Serializable]
public class Line
{
public int lineId;
public string type;
public string text;
}
[System.Serializable]
public class Scene
{
public int sceneId;
public string text;
public Line[] lines;
public Line GetLineByIndex(int idx)
{
return Array.Find(lines, l => l.lineId == idx);
}
}
[System.Serializable]
public class Npc
{
public int npcId;
public string name;
public Scene[] scenes;
public Scene GetSceneByIndex(int idx)
{
return Array.Find(scenes, s => s.sceneId == idx);
}
}
대사를 관리하는 Line 클래스를 Scene 단위 구조가 추가됐기 때문에 안으로 집어넣었다.
또한 멤버를 가져오는 함수들을 추가했다.
m_scene = m_npc.GetSceneByIndex(DialogueManager.Inst.SceneIdx);
...
m_line = m_scene.GetLineByIndex(_idx);
Scene 번호는 대화가 가능한 모든 오브젝트가 공유하기 때문에
DialogueManager에서 관리하도록 했다.
구현한 흐름 제어 요소는 네가지이다.
// 🖋️ 선택지
{
"lineId":0,
"type":"S",
"text":"서언태애애액지이이입니다[S]예_1/아니오_4[/S]"
},
// 🖋️ goto
{
"lineId": 1,
"type": "G",
"text": "선택확인 메세지 입니다. 예를 고르셨다구요?[G]2[/G]"
},
// 🖋️ SceneIndex 변경
{
"lineId": 100,
"type": "C",
"text": "[C]1[/C]"
}
// 🖋️ 일반
{
"lineId": 6,
"type": "N",
"text": "일반텍스트입니다."
},
대괄호 안에 키워드값으로 구분자를 넣고,
public string GetLineText()
{
if (m_line == null) return string.Empty;
// index에 해당하는 line 값을 가지고 옴
// ⭐ "서언태애애액지이이입니다[S]예_1/아니오_4[/S]"
string str = m_line.text;
// 키워드가 시작되는 []~[/] 부분의 인덱스 가져오기
int startMark = str.IndexOf('[');
int endMark = str.LastIndexOf(']');
if (startMark == -1 || endMark == -1)
{
#if UNITY_EDITOR
// N 타입이 아니면 키워드 []~[/]가 있어야 함
if (m_line.type.Equals("N") == false)
Debug.LogWarning("대사 형식이 type과 맞지 않습니다.");
#endif
LineTypeParse(string.Empty);
return str;
}
// []~[/] 사이의 값
// ⭐ "예_1/아니오_4"
string strParsed = str.Substring(startMark + 3, endMark - startMark - 6);
// 출력용 스트링 : []~[/] 부분 제거
// ⭐ "서언태애애액지이이입니다"
str = str.Remove(startMark, endMark - startMark + 1);
LineTypeParse(strParsed);
return str;
}
종류에 따라 파싱한다.
private void SetSelectLineInfo(string startMark)
{
selectNextLineIdx.Clear();
m_selectBalloon.SetActive(true);
// ⭐ "예_1/아니오_4"
string[] selects = startMark.Split('/');
// ⭐ "예_1", "아니오_4"
for (int i = 0; i < selects.Length; ++i)
{
string[] info = selects[i].Split('_');
selectTMP[i].text = info[0]; // ⭐ "예", "아니오"
selectNextLineIdx.Add(int.Parse(info[1])); // ⭐ "1", "4"
}
}