🧠 오늘의 핵심 정리
- 스토리 대화창 시스템을 기존 방식에서 ScriptableObject 기반으로 전환했습니다. (TalkManager/ObjectData 삭제)
- 플레이어 상호작용에서 NPC 감지(E 표시) 처리 개선 + 대화 진행을 DialogueManager로 일원화했습니다.
- 이벤트/엔딩 조건을 대사 흐름에 연결해서 “여동생 찾기 → 이벤트 스폰 → 엔딩” 구조를 만들었습니다.
- 드래그 UI에서 canvas를 FindObjectOfType로 찾던 방식을 DragCanvas 태그 기반으로 수정해 캔버스 문제를 해결했습니다.
- 추가로 배고픔/목마름 회복이 소비 아이템 사용과 연결되도록 PlayerController까지 연동했습니다.
💬 feat: 스토리 대화창 리팩토링 (TalkManager → DialogueManager)
오늘 작업의 핵심은 한 줄로 하면… “대화 시스템을 제대로 게임스럽게 만들기”였습니다.
기존에는 TalkManager가 Dictionary로 대사/초상화를 들고 있고, GameManager가 talkIndex로 다음 대사를 꺼내서 UIManager에 뿌리는 구조였는데요. 이게 만들 땐 빠르지만, 대사량이 늘어나거나 이벤트 조건이 붙는 순간 관리가 너무 힘들어질 것 같아서 구조를 갈아엎었습니다.
결론은 TalkData(ScriptableObject) + DialogueManager 단일 책임 구조로 정리했습니다.
TalkData.cs (대사 데이터 SO)
[CreateAssetMenu(fileName ="NewDialogue", menuName ="Dialogue")]
public class TalkData : ScriptableObject {
public string[] npcName;
public Sprite[] npcPortrait;
public string[] dialogueLines;
public bool isNpc = true;
}
이제 대사 내용/초상화/이름을 에디터에서 직접 만들고 교체할 수 있게 돼서, 확장성이 훨씬 좋아졌습니다. (이거 진짜 마음 편해요…)
DialogueManager.cs (대화 진행/종료 관리)
public void StartDialogue(TalkData talkData) {
currentTalk = talkData;
index = 0;
panel.SetActive(true);
ShowLine();
}
public void NextDialogue()
{
index++;
if(index < currentTalk.dialogueLines.Length) ShowLine();
else EndDialogue();
}
UIManager에서 대화 UI를 들고 있던 부분은 과감하게 제거했고, 이제는 DialogueManager가 패널을 켜고/끄고 대사 텍스트/초상화를 직접 갱신합니다.
정리하고 나니까 “대화 관련 버그는 DialogueManager만 보면 된다”가 돼서 디버깅도 훨씬 쉬워졌습니다.
🧍♂️ PlayerInteraction 개선 + NPC 상호작용(E 표시/대화 진입)
대화창이 정리되면, 그 다음은… “플레이어가 NPC를 어떻게 인식하고 대화하느냐”였는데요.
이번에는 PlayerInteraction에서 Raycast로 감지한 대상이 바뀌면 이전 NPC의 표시(E 인디케이터)를 꺼주고, 현재 감지된 NPC는 켜주는 방식으로 개선했습니다.
PlayerInteraction.cs - lastScan 기반 인디케이터 정리
private GameObject lastScan;
lastScan = scanObject;
scanObject = rayHit.collider != null ? rayHit.collider.gameObject : null;
if(lastScan != null && lastScan != scanObject)
{
NPC lastNpc = lastScan.GetComponent();
if(lastNpc != null) lastNpc.ShowIndicator(false);
}
if(scanObject != null)
{
NPC npc = scanObject.GetComponent();
if(npc != null) npc.ShowIndicator(true);
}
그리고 입력 처리도 기존에는 GameManager.Action/ShowNextDialogue로 흘러갔는데, 이제는 딱 깔끔하게 이렇게 바뀌었습니다.
E 키로 NPC 대화 시작 / 클릭으로 다음 대사
if(Input.GetKeyDown(KeyCode.E) && scanObject != null) {
NPC npc = scanObject.GetComponent<NPC>();
if (npc != null) npc.Interact();
}
if(DialogueManager.Instance.panel.activeSelf && Input.GetMouseButtonDown(0))
{
DialogueManager.Instance.NextDialogue();
}
이렇게 하니까 플레이어 입력 → NPC → DialogueManager 흐름이 딱 떨어져서, 더 이상 GameManager/UIManager가 대화에 끼지 않게 됐습니다. (이게 제일 만족 포인트였습니다)
🎬 feat: 이벤트/엔딩 조건 연결 (여동생 찾기 → 스폰 이벤트 → 엔딩)
그리고 오늘 제일 게임 같아진 부분… 대사 끝났을 때 이벤트가 발동되도록 연결한 겁니다.
DialogueManager.EndDialogue()에서 “어떤 대사였는지”를 기준으로 분기 처리를 넣었습니다.
DialogueManager.cs - 특정 대사 종료 시 이벤트 실행
private void EndDialogue() {
panel.SetActive(false);
if (currentTalk == findSisterDialogue)
{
findSister = true;
EnemySpawner.Instance.StartEvent();
}
if(currentTalk == endDialogue)
{
GameManager.Instance.ShowGameClear();
}
currentTalk = null;
}
그리고 ClearTrigger도 기존에는 GameClearPanel을 바로 띄웠는데, 이제는 엔딩 대사를 먼저 재생하고, 조건이 맞으면 클리어 패널까지 이어지도록 바꿨습니다.
ClearTrigger.cs - 클리어 트리거에서 엔딩 대사 호출
if (collision.gameObject.layer == LayerMask.NameToLayer("Player")) { DialogueManager.Instance.Ending(); }
또, 엔딩 대사가 여러 번 실행되는 것도 막기 위해 gameClear 플래그까지 추가했습니다. (이거 안 막으면 진짜… 한 번 꼬이면 답이 없더라고요)
feat: 마지막 대사 한 번만
private bool gameClear = false;
public void Ending()
{
if (endDialogue != null && findSister && !gameClear)
{
gameClear = true;
StartDialogue(endDialogue);
}
}
🧷 fix: canvas 문제 (드래그 아이콘 캔버스 고정)
그리고 중간에 제가 멘탈이 잠깐 나갔던 이슈… 드래그 UI 캔버스 문제였습니다.
ItemSlot에서 FindObjectOfType<Canvas>()로 캔버스를 잡아오니까 씬/계층에 따라 엉뚱한 캔버스가 잡힐 때가 있었고, 그 결과 드래그 아이콘이 원하는 레이어/위치에 안 뜨는 문제가 생겼습니다.
그래서 확실하게 DragCanvas 태그를 가진 오브젝트의 Canvas를 가져오도록 수정했습니다.
ItemSlot.cs - DragCanvas 태그로 캔버스 지정
GameObject obj = GameObject.FindGameObjectWithTag("DragCanvas"); canvas = obj.GetComponent<Canvas>();
이렇게 해두니까 씬이 바뀌어도 “드래그는 무조건 이 캔버스 위에서 돈다”가 보장돼서, UI가 훨씬 안정적으로 동작했습니다.
🍗 feat: 배고픔/목마름 회복 아이템 연동
오늘은 스토리/대화가 메인이긴 했는데, 틈틈이 생존 요소도 연결했습니다.
Consumable 아이템 사용 시 Hunger/Thirst를 올려야 하는데, 인벤토리에서 “값만 감소”하고 실제 스탯에는 반영이 안 되고 있어서 PlayerController에 Eat/Drink 함수를 추가로 연결했습니다.
Inventory.cs - 소비 아이템 사용 시 PlayerController 호출
public void UseItem(Item item) {
if (item.data.ItemType == ItemType.Consumable) {
if (item.data.HungerRestoration > 0) playerController.EatItem(item.data.HungerRestoration);
if (item.data.ThirstRestoration > 0)
playerController.DrinkItem(item.data.ThirstRestoration);
item.currentAmount--;
if (item.currentAmount <= 0) RemoveItem(item);
}
}
PlayerController 쪽에서는 max 값을 넘지 않도록 clamp 하고, UI도 즉시 갱신되게 처리했습니다.
PlayerController.cs - EatItem / DrinkItem
public void EatItem(int value) {
playerData.hunger += value;
playerData.hunger = Mathf.Min(playerData.hunger, playerData.maxHunger);
if (hungerUI != null) hungerUI.UpdateHunger(playerData.hunger, playerData.maxHunger);
}
public void DrinkItem(int value)
{
playerData.thirst += value;
playerData.thirst = Mathf.Min(playerData.thirst, playerData.maxThirst);
if (thirstyUI != null) thirstyUI.UpdateThirst(playerData.thirst, playerData.maxThirst);
}
🛡️ feat: 장비창 내구도 텍스트 표시
그리고 장비 UI도 조금 더 친절하게 만들었습니다. 이제 장비칸에 내구도 텍스트가 같이 뜨도록 수정했고, 피격 시 내구도가 깎이면 UI가 바로 갱신되게 이벤트를 분리했습니다.
Equipment.cs - OnDurabilityChanged 이벤트
public event Action OnDurabilityChanged;
public void DurabilityChanged()
{
OnDurabilityChanged?.Invoke();
}
UIEquipment.cs - 내구도 텍스트 갱신
equipment.OnDurabilityChanged += UpdateUI;
if(equipped != null)
slotDurability[slot].text = $"{equipped.durability}/{equipped.data.Durability}";
else
slotDurability[slot].text = "";
이제 플레이어가 맞을 때 “어? 장비가 닳고 있네”가 UI에서 바로 보여서 체감이 확 좋아졌습니다.
📌 오늘의 회고
오늘은 진짜… “대화 시스템 정리한 날”로 기억에 남을 것 같습니다.
TalkManager로 억지로 끌고 가도 당장은 되는데, 미래를 생각하면 분명 폭탄이 될 것 같아서 과감하게 리팩토링했거든요. 근데 정리하고 나니까 구조도 깔끔해지고, 이벤트/엔딩까지 연결할 수 있는 길이 열려서 너무 만족스럽습니다.
중간중간 캔버스 문제나 인코딩 깨짐 같은 것도 있었지만… 오늘은 전체적으로 “게임이 진짜 게임이 되어가는 느낌”이 들어서 기분이 좋았습니다.
'내일배움캠프 본캠프' 카테고리의 다른 글
| [내일배움캠프 49일차 TIL] 최종 프로젝트 1일차 - 최종 프로젝트 시작과 팀 협업 규칙 정리 (0) | 2025.12.08 |
|---|---|
| [내일배움캠프 48일차 TIL] 프로토타입 6일차 '발표 끝' (0) | 2025.12.05 |
| [내일배움캠프 46일차 TIL] 프로토타입 4일차 '대사창' (0) | 2025.12.03 |
| [내일배움캠프 45일차 TIL] 프로토타입 3일차 'Json 데이터로 아이템 제작' (0) | 2025.12.02 |
| [내일배움캠프 44일차 TIL] 프로토타입 2일차 '인벤토리 시작' (0) | 2025.12.01 |