StringBuilder
StringBuilder 는 문자열을 자주 이어 붙이거나 수정할 때 사용하는 특수한 클래스이다.
C# 에서 문자열 ( String ) 은 불변 ( Immutable ) 이라서 + 연산을 할 때마다 새로운 문자열 객체를 계속 생성한다.
그래서 반복문에서 문자열을 계속 더하면 성능이 매우 떨어지는 문제가 발생한다.
그 문제를 해결해주는게 StringBuilder 이다.
StringBuilder 핵심 개념
문자열을 변경해도 새로운 객체를 만들지 않는다
StringBuilder 는 내부 버퍼에서 문자열을 수정하기 때문에
+ 연산처럼 계속 새 객체를 만들 필요가 없다 → 빠르고 메모리 효율적이다
using UnityEngine;
using UnityEngine.InputSystem;
public class PlayerInteraction : MonoBehaviour
{
TalkableBase talkTarget;
// BallDialogue 같은 구체화 된 것을 들고 있는 것이 아닌 TalkableBase 추상 객체를 들고 있는다 SOLID
public GameObject Fkey; // F키 상호작용. 안내 문구 껏다켰다 하려고 넣었음
private void OnTriggerEnter(Collider other)
{
talkTarget = other.GetComponent<TalkableBase>(); // 플레이어가 만약 게임오브젝트에 충돌을 감지했는데 그 오브젝트에 이거 있으면?
Fkey.SetActive(true); // F키 UI 띄워라
}
private void OnTriggerExit(Collider other)
{
if(talkTarget == other.GetComponent<TalkableBase>()) // 내가 대화중이었던 오브젝트가 맞으면?
{
talkTarget = null; // 대화 상대 정보 삭제
Fkey.SetActive(false); // F키 UI 꺼라
}
}
private void Update()
{
if(talkTarget != null && Keyboard.current.fKey.wasPressedThisFrame)
{
DialogueManager manager = FindFirstObjectByType<DialogueManager>(); // 업데이트마다 이거 하는건 비효율적인 코드. 예시라서 그냥 작성함
// 매니저를 스타트와 동시에 찾는다
// 매니저를 그냥 직렬화로 꽃아넣어둔다
// 싱글톤으로 매니저를 활용한다
talkTarget.Talk(manager);
}
}
}
using UnityEngine;
public class BallDialogue : TalkableBase
{
private void Awake()
{
dialogueLines = new string[]
{
"공 : 나는 공이야. 할 말이 있어.",
"공 : 근데 아마 TMP 한글 안구워놔서 내 말은 들리지 않을거야.",
"Ball : Remember, use StringBuilder"
};
}
// 사실 이런거 잘 리메이크하면, csv로부터 불러와서 대화집을 불러오는 방식으로 가능할 것
}
using UnityEngine;
using System.Text; // 문자열 최적화에 필요한 내용
// 모든 대화 가능한 대상들은 이걸 상속받게 한다
public abstract class TalkableBase : MonoBehaviour
{
protected string[] dialogueLines; // 이건 상속받은 자식 객체에서 채울 예정 , 진짜 대사들이 들어갈 예정
protected int currentLine;
//protected string fullText = ""; // 누적된 문자열을 기억시킬 목적
protected bool isTalking;
protected StringBuilder sb = new StringBuilder(); // 문자열을 유연하게 해주는 객체
// 모든 Talkable 은 Talk 메서드를 가진다
public void Talk(DialogueManager manager)
{
if(!isTalking) // 대화중이지 않았다면?
{
isTalking = true; // 대화중으로 변경
currentLine = 0; // 대화 현황 초기화
sb.Clear(); // 스트링빌더에게 클리어 지시
//fullText = ""; // 대화 문자열 초기화 (불변성 때문에 제외)
//manager.ShowDialogue(fullText); // 매니저에게 풀 텍스트 던져주도 읽으라고 지시한다
manager.ShowDialogue(sb.ToString());
ShowNextLine(manager);
}
else // 대화 중이었다면
{
ShowNextLine(manager);
}
}
protected virtual void ShowNextLine(DialogueManager manager)
{
if(currentLine < dialogueLines.Length) // 현재 보고 있는 줄이 전체 대화 내용보다 작다면?
{
//fullText += dialogueLines[currentLine] + "\n";
sb.AppendLine(dialogueLines[currentLine]); // 차곡차곡 저 문자열들이 누적
manager.ShowDialogue(sb.ToString()); // 갱신된 텍스트 띄울 목적 , 위 과정을 통해 누적된 최종 문자열을 합쳐서 한번에 출력
currentLine++; // 현재 줄 증가
}
else // 대화를 다 출력했다면?
{
manager.HideDialogue();
isTalking = false;
}
}
//void Test()
//{
// string s = "Hello";
//
// s += " World"; // 실제로는 "Hello" + " World" 를 새로 만들어서 s에 다시 대입
//
// // String immutable, 불변 객체. 한번 만든 문자열은 절대 변하지 않는다.
//
// s[1] = 'e'; // 이런거 에러난다. 문자열 하나 통으로 기억하기에, 개별변경 불가능
//}
}
using UnityEngine;
using UnityEngine.InputSystem;
public class PlayerMovement : MonoBehaviour
{
public float moveSpeed = 5f;
private void Update()
{
// WASD / 방향키 자동 지원
Vector2 input = Keyboard.current != null ? new Vector2
(
(Keyboard.current.dKey.isPressed ? 1 : 0) - (Keyboard.current.aKey.isPressed ? 1 : 0),
(Keyboard.current.wKey.isPressed ? 1 : 0) - (Keyboard.current.sKey.isPressed ? 1 : 0)
)
: Vector2.zero;
Vector3 dir = new Vector3(input.x, 0f, input.y);
transform.Translate(dir * moveSpeed * Time.deltaTime);
}
}
using UnityEngine;
using TMPro;
public class DialogueManager : MonoBehaviour
{
public GameObject dialoguePanel; // 대화창 전체 패널. 껏다켰다 할거라서 기억시킴
public TextMeshProUGUI dialogueText; // 대화 내용 표시할 Text 컴포넌트
// 패널 키고 대화 표시하는 메서드
public void ShowDialogue(string fullText)
{
dialoguePanel.SetActive(true); // 대화 시작할거니까 일단 패널 켜서 UI 보여준다
dialogueText.text = fullText; // 인자값으로 넘어온 내용을 UI 텍스트에 뿌려준다
}
public void HideDialogue()
{
dialoguePanel.SetActive(false); // 사실 텍스트야 비울 핖요 없이 그냥 패널만 꺼도 무방하다
dialogueText.text = ""; // 혹시 모를 예외 처리
}
}
'📖TIL' 카테고리의 다른 글
| 251230 (0) | 2025.12.30 |
|---|---|
| 251210 Loading (0) | 2025.12.10 |
| 251210 Github Issue & Github Projects (0) | 2025.12.10 |
| 251209 CSV 파싱 (0) | 2025.12.09 |
| 251208 옵저버 패턴 복습 (0) | 2025.12.08 |