다이얼로그 구현하기

2024. 5. 17. 14:14·Unity/Tip
반응형
#region
using System;
using System.Collections;

using TMPro;

using UnityEngine;
using UnityEngine.UI;
#endregion

public class DialogSystem : MonoBehaviour
{
	[SerializeField] Speaker[] speakers;
	[SerializeField] DialogData[] dialogs;
	[SerializeField] bool isAutoStart = true;
	bool isFirst = true;
	int currentDialogIndex = -1;
	int currentSpeakerIndex;
	const float TypingSpeed = 0.1f;
	bool isTypingEffect;

	bool isClicked;

	void Setup()
	{
		for (int i = 0; i < speakers.Length; ++i)
		{
			SetActiveObjects(speakers[i], false);
			speakers[i].imageDialog.GetComponent<Button>().onClick.AddListener(() => isClicked = true);
			speakers[i].speakerImage.gameObject.SetActive(true);
		}

		Debug.Log("Dialog SetUp");
	}

	public bool UpdateDialog()
	{
		if (isFirst)
		{
			Setup();

			if (isAutoStart) SetNextDialog();

			isFirst = false;
		}

		if (!isClicked) return false;

		isClicked = false;
		if (isTypingEffect)
		{
			isTypingEffect = false;

			StopCoroutine("OnTypingText");
			speakers[currentSpeakerIndex].textDialogue.text = dialogs[currentDialogIndex].dialogue;

			return false;
		}

		if (dialogs.Length > currentDialogIndex + 1) { SetNextDialog(); }
		else
		{
			EndDialog();
			return true;
		}

		return false;
	}

	void SetNextDialog()
	{
		SetActiveObjects(speakers[currentSpeakerIndex], false);

		currentDialogIndex++;

		currentSpeakerIndex = dialogs[currentDialogIndex].speakerIndex;
		// SoundManager.Instance.PlayOnlyOneEffect(dialogs[currentDialogIndex].effectSound);
		// SoundManager.Instance.PlayBackgroundMusic(dialogs[currentDialogIndex].backgroundSound);
		SetActiveObjects(speakers[currentSpeakerIndex], true);

		if (speakers[currentSpeakerIndex].textName is not null) speakers[currentSpeakerIndex].textName.text = dialogs[currentDialogIndex].name;

		StartCoroutine("OnTypingText");
	}

	void SetActiveObjects(Speaker speaker, bool visible)
	{
		speaker.imageDialog.gameObject.SetActive(visible);
		speaker.textName?.gameObject.SetActive(visible);
		speaker.textDialogue.gameObject.SetActive(visible);

		Color color = speaker.speakerImage.color;
		color.a = visible ? 1 : 0f;

		speaker.speakerImage.color = color;
	}

	IEnumerator OnTypingText()
	{
		int index = 0;

		isTypingEffect = true;

		while (index < dialogs[currentDialogIndex].dialogue.Length)
		{
			speakers[currentSpeakerIndex].textDialogue.text = dialogs[currentDialogIndex].dialogue.Substring(0, index);

			index++;

			yield return new WaitForSeconds(TypingSpeed);
		}

		isTypingEffect = false;
	}

	void EndDialog()
	{
		foreach (Speaker speaker in speakers)
		{
			SetActiveObjects(speaker, false);
			speaker.speakerImage.gameObject.SetActive(false);
		}

		// SoundManager.Instance.StopBackgroundMusic();
	}
}

[Serializable] public struct Speaker
{
	public Image speakerImage;
	public Image imageDialog;

	public TextMeshProUGUI textName;
	public TextMeshProUGUI textDialogue;
}

[Serializable] public struct DialogData
{
	public int speakerIndex;
	public string name;

	[TextArea(3, 5)]
	public string dialogue;

	public AudioClip effectSound;
	public AudioClip backgroundSound;
}

 

사용 방법

아래의 사진과 같이 화자(Speakers)들을 생성한 뒤, 다이얼로그에 화자의 인덱스를 맞게 생성하면 된다.

배경음악이나 효과음을 사용하고 싶다면, 해당 다이얼로그에 오디오 클립을 넣어주고 주석처리된 부분처럼 Sound Player를 연결해 오디오를 재생할 수 있다. 

 

다이얼로그가 끝나는 시점은 UpdateDialog() 메서드가 true를 반환 할 때로,

IEnumerator Dialog() { yield return new WaitUntil(() => dialogSystem.UpdateDialog()); }

이처럼 코루틴으로 끝날 때 까지 대기할 수 있다. 

 

타이핑 효과로 글자가 전부 출력되지 않은 상황에 Image Dialog를 클릭 시 타이핑 효과는 종료되고 즉시 텍스트가 전부 출력된다. 

주의 사항

Image Dialog는 Button 컴포넌트를 장착해야 한다. 

 

테스트

테스트

 

 

저작자표시 비영리 변경금지 (새창열림)

'Unity > Tip' 카테고리의 다른 글

Unity 인터넷 연결 확인하기  (0) 2024.05.31
Google Mobile Ads Unity Plugin v9.0.0 업데이트 정보  (0) 2024.05.23
Unity 코드 문서화 : summary 태그 활용  (3) 2024.04.26
뷰포트 영역 안에 있는지 검사하는 방법  (1) 2024.03.21
콜라이더 충돌 검사 : Physics.Overlap vs NonAlloc  (0) 2024.01.05
'Unity/Tip' 카테고리의 다른 글
  • Unity 인터넷 연결 확인하기
  • Google Mobile Ads Unity Plugin v9.0.0 업데이트 정보
  • Unity 코드 문서화 : summary 태그 활용
  • 뷰포트 영역 안에 있는지 검사하는 방법
코샵
코샵
나의 코딩 일기장
    반응형
  • 코샵
    끄적끄적 코딩 공방
    코샵
    • 분류 전체보기 (724) N
      • 상품 추천 (223) N
      • MongoDB (4)
      • 하드웨어 (16) N
      • 일기장 (4)
      • Unity (138)
        • Tip (41)
        • Project (1)
        • Design Pattern (8)
        • Firebase (6)
        • Asset (2)
      • 파이썬 (13)
        • Basic (41)
        • OpenCV (8)
        • Pandas (15)
        • PyQT (3)
        • SBC(Single Board Computer) (1)
        • 크롤링 (14)
        • Fast API (29)
        • Package (6)
      • Linux (4)
      • C# (97)
        • Algorithm (11)
        • Window (7)
      • TypeScript (41)
        • CSS (10)
      • Git (11)
      • SQL (5)
      • Flutter (10)
        • Tip (1)
      • System (1)
      • BaekJoon (6)
      • Portfolio (2)
      • MacOS (1)
      • 유틸리티 (1)
      • 서비스 (6)
      • 자동화 (3)
      • Hobby (10)
        • 물생활 (10)
        • 식집사 (0)
  • 인기 글

  • 태그

    appdevelopment
    devlife
    codingtips
    cv2
    C#
    Python
    리스트
    rtsp
    learntocode
    programmerlife
    codingcommunity
    스마트스토어리뷰
    unity
    긴유통기한우유
    리뷰관리
    믈레코비타멸균우유
    programming101
    셀레니움
    파이썬
    카페24리뷰이관
    상품 리뷰 크롤링
    라떼우유
    리뷰이관
    스크립트 실행
    카페24리뷰
    쇼핑몰리뷰
    ipcamera
    스크립트 실행 순서
    유니티
    list
  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
코샵
다이얼로그 구현하기
상단으로

티스토리툴바