킹머핀의 제작 일지
글자 출력 과정 그리고 혼란파티 본문
어우, 내 수준보다 복잡한 기능을 만드려니 또 자꾸 달팽이마냥 꾸물거리고나 있다. 이럴 땐 역시 글로 써 봐야지. 그리고 역시 도움이 됐는지 평가해보자.
- JSON 파일에서 대사와 특수 효과를 가져온다.
- Typewriter text 액션으로 한 글자씩 추가한다?
- 특수 효과가 있다면 추가한 내용을 다시 한 글자씩 적용한다?
- 2~3을 마지막 글자까지 반복한다.
1. JSON 파일에서 대사와 글자 효과를 가져온다.
이 때 BBcode 태그는 대사에 포함해서 작성하겠지만, 특수 효과(BBcode를 이용한 실시간 효과) 종류는 어디에 적을지가 관건.
특수 효과도 문장의 일부에만 적용하고 싶다면 대사에 포함해야 적절하다.
하지만 기능은 나아중에 여유가 있을 때나 구현하자. 지금은 따로 적어놓기로.
만약 구현하게 된다면 이런 과정이겠지.
- 대사에 BBcode와 특수 효과 종류 모두 특정 특수문자로 치환해서 작성한다(또는 태그를 분석한다).
- BBcode의 특수문자는 다시 해당하는 태그로 변환한다.
- 특수 효과의 특수문자는 순서를 저장하고 지운다.
- 텍스트를 하나씩 출력할 때 순서 안의 각 글자에 특수 효과를 적용한다.
2. Typewriter text 액션으로 한 글자씩 추가한다?
왜 따로 함수를 정의하지 않고 이 액션을 이용해야 하냐면, 그래야 BBCode가 노출되지 않고, 미리 단어 줄 맞춤이 되기 때문이다.
Illume_Demo에서는 따로 함수를 정의했고, 줄 맞춤을 위해 미리 모든 글자를 적용한 후 차지하는 길이에 따라 개행 문자를 넣은 후 한 글자씩 출력했다. BBcode도, 문장의 일부에 태그(리치 텍스트)도 넣지 못 했다. 주로 말풍선의 움직임으로 표현했다. 그러나 Construct 3의 Typewriter text 액션은 이를 구현했나보다.
유니티의 TextMesh Pro는 모든 글자를 개별 텍스트 매쉬로 표시해서 특수 효과를 자유롭게 적용할 수 있다. 글자 하나하나가 객체라서 가능한가? 정확히는 모르겠다. 정확히 알고싶네.. 그러다 우연히 발견한 아래 영상에서 메쉬 정점 인덱스를 이용한다는 사실을 알아냈다.
그리고 DoTween도 DoText()라는 Typewriter 함수를 지원한다.
Frostory의 개발자 중 한 분의 설명으로는 유니티 '기본 텍스트'의 글자 아이콘 매쉬를 글리프 계산으로 수정하는 방법을 사용한다고 합니다. '기본 텍스트'가 캔버스에 표시하는 'UI Text'인지, 매쉬 자체인 3차원 'Text Mesh'인지, 아님 그보다 원초적인 'GUI Text'인지는 모르겠네요. 기회가 되면 다시 질문을.. ㅠ
비슷한 방법으로, 한 객체에 모든 글자를 출력하지 않고 한 글자 당 한 객체를 생성하는 무식한 방법이 있다. 성능에 크게 무리가 가진 않을 것이다. 그보다 많은 객체를 생성해도 쉽사리 버벅이지 않으니. 잊을 뻔했는데, 이러한 방법은 문장의 일부에 특수 효과를 쉽게 적용할 수 있지만 줄 맞춤 기능부터 글자 간 간격까지 모두 구현해야 한다!
잠깐, 어차피 위에서 안 하기로 했잖아. 어려운 문제부터 고민하면 비효율적이라고. 정신 차려!!!!!!! 게다가 내가 이 글을 여기까지 쓰면서 간과한 점이 두 가지 있다.
- BBcode는 태그를 닫지 않으면 문장의 끝까지 적용된다. 즉 무조건 Typewriter가 답은 아니다.
- Typewriter은 '기간' 인수가 0이면 즉시 완료한다. 즉 완료할 텍스트와 이 액션을 실행하는 주기를 조절하면 과정이 간단해진다. 하지만 줄 맞춤이 안 되기도 하고 한 글자마다 BBcode를 적용하는 방식을 이용한다면 필요 없긴 한데..
아 그래서 Construct 3의 Typewriter을 쓰겠단 거야 말겠단 거야! 읽는 사람도 아리송하겠네 (내가 좋으려고 쓰는 글이긴 합니다)
그러니까 늘 하던거, 생각나는 방법을 모두 나열하며 평가해보자. 이걸 처음부터 했어야 하는데.
- 보이지 않는 임시 텍스트 인스턴트에 Typewriter로 출력하고, 그 내용을 보이는 텍스트 인스턴트에 복사한다. 특수 효과가 있다면 복사한 내용에 적용한다.
이 글의 3번과 이 목록의 두 번째 항목이 다르지 않음을 확인. - 표시할 내용의 범위를 늘리며 Typewriter로 즉시 출력한다. 특수 효과가 있다면 그 내용에 적용한다.
BBcode를 제외한 문자에만 적용할 수 있는 코드를 요구함. - 미리 모든 글자를 출력한 후 BBcode로 배경과 같은 색으로 바꾼 후 한 글자씩 흰 색으로 나타나게 한다.
이 역시 BBcode를 제외한 문자에만 적용할 수 있어야 하며, 배경 색이 일정하지 않은 위치에서 사용할 수 없다. - Typewriter을 사용하지 않고, 이 글의 1번에서 짐작한 목록의 첫 번째 항목(대사에 BBcode와 특수 효과 종류 모두 특정 특수문자로 치환해서 작성한다)을 이용한다.
음.. 아무리 생각해도 단점이 없다. 오히려 제일 쉽다. 심지어 문장의 일부에도 특수 효과를 적용하기 쉽다..
'bbcode typewriter', 'bbcode typing', 'typewriter text effects', 'typing animated text', 'rich text typewriter', 'rich text typing' 등 다양한 검색어로 다양한 글을 훑어본 결과, 이 기능은 태그를 분석하고 제거한 뒤, 출력할 때 한 글자씩 다시 태그를 붙이는 방법이 유력하다.
하지만 태그를 분석하는 코드가 매우 복잡한데, 이를 대폭 단순화할 대책이 바로 특수 문자로 치환하는 것이다. 어차피 내가 전부 작성할 건데 표준을 따라야 할 필요가 없다.
나는 왜 진작에 이 방법을 채택할 생각을 못 했을까? 음.. 나는 처음엔 특수 효과와 같은 이벤트를 이전에 알게 된 함수 매핑으로만 구현할 생각이었다. 그러면 문장의 일부에 해당하는 문자열 인덱스를 일일이 정하고 적용하는 과정이 매우 번거롭기 때문에, 문장의 일부가 아닌 전체에만 적용하기로 했다. 그 다음엔 BBcode의 태그와 특수 문자를 병용하는 방법을 고려했는데, 태그를 피해서 문장의 일부에 특수 효과를 적용할 묘안을 생각해내기 어려웠다(사실 이것도 바로 시도했다면 금방 구현했을지도 모른다). 그래서 포기하고 남은 미련을 만약 구현하게 됐을 때의 과정을 적으며 떨쳐버리려 했다. 그렇게 나도 모르게 최선의 방법을 적었다. 그러다 위의 글을 발견했는데, 반복문에서 특수 문자를 인식하면 건너뛰고 해당 효과의 bool 변수를 참으로 바꾸어 한 글자씩 태그를 붙이며 출력하는 아주 단순한 원리였다. 저 글이 없었어도 알아차리지 못 했을 것이다.
아 맞다. 한 글자씩 출력하면 자동으로 줄 맞춤이 되지 않는다고 했지? 또 간과했네..?
그럼 이 방법으로 특수 문자를 모두 태그로 변환해서 지역변수에 저장해뒀다가 Typewriter로 출력하는 건? 그러면 출력 중엔 특수 효과를 넣을 수 없잖아. 어, 그럼 애초부터 Typewriter은 사용할 수 없었네..? (환장)
또 생각난게, 쉼표나 마침표와 같은 특수 문자가 나타났을 때 잠깐 멈추는 기능도 Construct 3의 Typewriter에 없다. ㅎㅋ
3. 특수 효과가 있다면 추가한 내용을 다시 한 글자씩 적용한다?
Typewriter text 액션은 마지막 글자를 추가하기 전에 다른 글자가 난입하면 즉시 이상한 순서로 내용을 채워서 마무리한다. 쉽게 말하면, 이 액션이 작동하는 와중에 텍스트를 수정하면 안 된다.
그래서 글자 전체에 특수 효과를 추가하고 싶다면 임시 텍스트 인스턴스에 Typewriter로 작성하는 중에 그 내용을 가져와 적용하면 될 거라고 예상했다. 진짜 되는지 직접 시도해보았는데, Typewriter로 작성한 문장이라도 문자의 특정 순서에 BBcode가 포함되어서 까다롭다.
자, 이제 Typewriter은 쓸모 없음이 분명해졌으니 제발 그만 알아보자. 잠깐, 그럼 특수 효과를 먼저 적용하고 출력하는 도중에 특수 문자로 치환한 태그를 적용하면 어떨까? 특수 문자를 치환하기 전에 Typewriter로 출력하니 길이는 약간 길어지겠지만 줄 맞춤으로 인해 더 일찍 개행된다고 가독성에 큰 차이는 없을 것이다.
..이 글의 2번을 다 썼다. (글 쓰는 순서가 뒤죽박죽이다) 이제 특수 문자 치환으로 태그를 쉽게 붙이는 방법도 안다. 글자 전체가 아니라 일부에도 특수 효과를 적용할 수 있다. 바로 위 문단은 이제 쓸모가 없다.
그러나 바로 위 문단도 쓸모가 없다는 사실을 깨달았다. 작성 중인 텍스트와 작성 도중에 가져온 텍스트는 또 다르잖아? 작성 중인 텍스트는 이미 줄 맞춤이 되어 있는데, 작성 도중에 가져온 텍스트는 그냥 텍스트일 뿐이잖아?
((내가 뭘 하고 있는지 잊혀지고 있다))
TextMesh Pro처럼 모든 글자가 개별 메쉬라면 미리 모든 글자를 출력해 줄 맞춤이 이루어진 상태에서 투명도를 이용해 한 글자씩 표시할 수 있었을 텐데. BBcode도 HTML이나 리치 텍스트처럼 투명도는 조절할 수 없을 테고..
..라고 생각한 뒤 바로 검색해보았다. HTML도 된다. 리치 텍스트도 된다고.
그럼 BBcode도???
된다!
으아악! 잘 된다!!
결국 찾아낸 것이다! 방법을!
(방금 알게 된 사실 : 이 글의 2번 항목에서 나열한 방법 목록의 세 번째 항목의 링크에서 이미 설명하고 있는 방법.) (그래도 저 땐 BBcode와 특수 효과를 적용하는 방법부터 확신이 전혀 없었다)
(다다음날 알게 된 사실 : 같은 기능을 하는 hide 태그도 있었다. 알파값이고 자시고 그냥 글자를 숨길 수 있는지부터 알아봤어야 했다.)
이 문제 하나로 2~3일이 걸렸다는 사실이 허무하다. 남들은 몇 시간이면 해결하는 문제였겠지..? 아니 해결할 문제는 맞나?😭
4. 2~3을 마지막 글자까지 반복한다.
정리 :
- JSON 파일에서 특수 문자와 함께 작성한 대사를 가져와 문자열 변수에 저장한다.
- 매 프레임마다 저장한 특수 문자를 한 글자씩 BBcode로 변환하며 모두 출력한다. (이 때 일반 태그는 나중에 닫아도 된다.)
- 마지막으로 표시할 글자의 뒤에 [hide]를 추가한다. (이 때 뒤의 특수 문자는 변환하지 않아도 된다.)
이번 글 요약 : 강만두의 우당탕탕 워크플로우
이번 글을 쓰며 도움이 되었는가? 시간 대비 이득이 컸는가?
내 생각의 흐름이 드러난 글이다. 유익한, 호기심을 부르는 예시도 찾았고, 생각할 수 있는 대부분의 방법을 정리했으며, 결과적으로 최선의 방법을 찾았다.
다만 이 글을 쓰면서마저도 버벅였다. 나만의 문제 해결 과정을 정해두면 더 도움이 될 것. 가장 먼저 생각나는 방법을 모두 나열하며 평가하고 어떤 기능을 만들 수 있거나 만들고 싶은지를 써본다던지.
'인디 게임 개발 > 개발 일지' 카테고리의 다른 글
로그) 대사 출력 구현 (0) | 2021.03.04 |
---|---|
로그) 글자 출력 구현 그리고 환장파티 (0) | 2021.02.26 |
대사 불러오기 기능 수정 (0) | 2021.02.17 |
대사 불러오기 (0) | 2021.02.16 |
화살표 생성, 입력 반응, 상호작용 (0) | 2021.02.13 |