인물정보, 소지품 분리

This commit is contained in:
2026-07-31 11:51:50 +09:00
parent 23e93a67f8
commit 4dc22eb32b
36 changed files with 598 additions and 120 deletions

View File

@@ -0,0 +1,27 @@
using UnityEngine;
// 증거품 항목 하나 — 소지품이거나 인물이거나.
//
// 분류(소지품/인물 정보) 필드가 여기 없는 것은 의도된 것이다.
// 분류는 EvidenceDatabase의 어느 목록에 넣었는지로 결정된다 — 항목에도 분류 필드를 두면
// "목록 위치"와 "필드 값"이 어긋날 수 있으므로, 아예 어긋날 수 없게 한쪽만 남겼다.
// 두 분류가 이름·그림·설명이라는 같은 모양을 쓰므로 타입도 나누지 않는다.
//
// Id가 곧 "제시 키"다 — 대화 노드의 HiddenBranch.Key와 같은 값을 쓰면,
// 그 노드가 재생되는 동안 이 항목을 제시했을 때 해당 히든 분기가 열린다.
// (DialogTouchZone의 부위 키와 완전히 같은 통로를 쓴다)
[CreateAssetMenu(menuName = "Evidence/Evidence Data")]
public class EvidenceData : ScriptableObject
{
[Tooltip("고유 Id — 저장 파일과 히든 분기 Key에 쓰인다. 비우면 에셋 이름")]
public string Id;
[Tooltip("증거품창에 표시할 이름")]
public string Name;
[Tooltip("증거품창에 표시할 그림 (소지품 사진 / 인물 초상)")]
public Sprite Icon;
[Tooltip("증거품창에 표시할 설명")]
[TextArea(2, 5)] public string Description;
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 70ed680488473ed44ad380007f918f67

View File

@@ -0,0 +1,66 @@
using System.Collections.Generic;
using UnityEngine;
// 증거품의 하위 분류. 어느 목록에 들어 있는지가 곧 분류다 (EvidenceDatabase 참고).
public enum EvidenceCategory
{
[InspectorName("소지품")] Item,
[InspectorName("인물 정보")] Profile,
}
// 게임에 존재하는 모든 증거품 항목의 목록 (StoryDatabase와 같은 "단일 원본" 역할).
//
// 분류마다 목록을 따로 둔다. 데이터를 넣는 사람은 드롭다운을 고를 필요 없이
// 해당 목록에 끌어다 놓기만 하면 되고, 분류가 두 곳에 적히지 않으니 어긋날 수도 없다.
//
// 저장 파일에는 Id 문자열만 남으므로, Id → EvidenceData 복원은 이 에셋이 담당한다.
// 게임에 하나만 만들어 EvidenceHud에 꽂아 쓴다.
[CreateAssetMenu(menuName = "Evidence/Evidence Database")]
public class EvidenceDatabase : ScriptableObject
{
[Tooltip("소지품 — 물건 증거품")]
[SerializeField] private List<EvidenceData> _items = new();
[Tooltip("인물 정보 — 사건 관계자")]
[SerializeField] private List<EvidenceData> _profiles = new();
public IReadOnlyList<EvidenceData> GetEntries(EvidenceCategory category)
=> category == EvidenceCategory.Item ? _items : _profiles;
// Id로 항목을 찾고 그 분류까지 함께 알려준다. 어느 목록에도 없으면 null.
public EvidenceData FindById(string id, out EvidenceCategory category)
{
category = EvidenceCategory.Item;
if (string.IsNullOrEmpty(id)) return null;
var found = FindIn(_items, id);
if (found != null) return found;
category = EvidenceCategory.Profile;
return FindIn(_profiles, id);
}
public EvidenceData FindById(string id) => FindById(id, out _);
private static EvidenceData FindIn(List<EvidenceData> list, string id)
{
foreach (var entry in list)
{
if (entry == null) continue;
string entryId = string.IsNullOrEmpty(entry.Id) ? entry.name : entry.Id;
if (entryId == id) return entry;
}
return null;
}
#if UNITY_EDITOR
// 같은 항목을 두 목록에 넣으면 분류가 모호해지므로(먼저 찾은 쪽이 이긴다) 넣는 즉시 알려준다.
private void OnValidate()
{
foreach (var entry in _items)
if (entry != null && _profiles.Contains(entry))
Debug.LogWarning($"[EvidenceDatabase] '{entry.name}'이(가) 소지품과 인물 정보 " +
"양쪽에 있습니다 — 한쪽에서 빼주세요", this);
}
#endif
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: f6c0a1fdc73b78049aa22e3aa4e84290