다이얼로그 구현하기

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 태그 활용
  • 뷰포트 영역 안에 있는지 검사하는 방법
코샵
코샵
나의 코딩 일기장
    반응형
  • 코샵
    끄적끄적 코딩 공방
    코샵
    • 분류 전체보기 (730)
      • 스마트팜 (1)
      • 상품 추천 (223)
      • DataBase (0)
        • MongoDB (4)
        • PostgreSQL (0)
      • 하드웨어 (19)
      • 일기장 (4)
      • 파이썬 (131)
        • Basic (42)
        • OpenCV (8)
        • Pandas (15)
        • PyQT (3)
        • SBC(Single Board Computer) (1)
        • 크롤링 (14)
        • Fast API (29)
        • Package (6)
      • Unity (138)
        • Tip (41)
        • Project (1)
        • Design Pattern (8)
        • Firebase (6)
        • Asset (2)
      • Linux (5)
      • C# (97)
        • Algorithm (11)
        • Window (7)
      • TypeScript (51)
        • 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)
  • 인기 글

  • 태그

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

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

티스토리툴바