데이터 파이프라인 개선 및 포탈 로직 생성

csv import 시 자동으로 완전한 프리팹이 생성될 수 있도록 함.
This commit is contained in:
2026-02-01 00:29:22 +09:00
parent b54e016283
commit 2593b6dd37
48 changed files with 11897 additions and 45 deletions

View File

@@ -12,6 +12,27 @@ namespace Northbound.Editor
{
private static readonly string GAMEDATA_PATH = Path.Combine(Application.dataPath, "..", "GameData");
private static readonly string SO_BASE_PATH = "Assets/Data/ScriptableObjects";
private static readonly string PREFAB_BASE_PATH = "Assets/Prefabs";
private static readonly string TEMPLATE_BASE_PATH = "Assets/Data/Templates";
private static System.Collections.Generic.Dictionary<string, IPrefabSetup> prefabSetups =
new System.Collections.Generic.Dictionary<string, IPrefabSetup>();
static CSVToSOImporter()
{
RegisterPrefabSetups();
}
private static void RegisterPrefabSetups()
{
prefabSetups.Clear();
prefabSetups["Monster"] = new MonsterPrefabSetup();
// To add new data types, create a class implementing IPrefabSetup
// Example:
// prefabSetups["Tower"] = new TowerPrefabSetup();
// prefabSetups["Player"] = new PlayerPrefabSetup();
}
[MenuItem("Tools/Data/Import All CSV")] // 메뉴 추가 (편의성)
public static void ImportAll()
@@ -54,6 +75,7 @@ namespace Northbound.Editor
if (lines.Length < 2) return false;
var headers = ParseCSVLine(lines[0]);
var createdSOs = new List<ScriptableObject>();
for (int lineIndex = 1; lineIndex < lines.Length; lineIndex++)
{
@@ -72,7 +94,12 @@ namespace Northbound.Editor
}
string assetName = GetAssetName(so, lineIndex);
AssetDatabase.CreateAsset(so, Path.Combine(outputPath, $"{assetName}.asset"));
string soPath = Path.Combine(outputPath, $"{assetName}.asset");
AssetDatabase.CreateAsset(so, soPath);
createdSOs.Add(so);
GenerateOrUpdatePrefab(schemaName, assetName, so, lineIndex);
}
AssetDatabase.SaveAssets();
@@ -148,11 +175,97 @@ namespace Northbound.Editor
return l == "true" || l == "1" || l == "yes";
}
if (targetType == typeof(string)) return value.Replace("\\n", "\n");
return Convert.ChangeType(value, targetType);
return Convert.ChangeType(value, targetType);
}
catch { return null; }
}
private static int GetColumnIndex(string[] headers, string columnName)
{
for (int i = 0; i < headers.Length; i++)
{
if (headers[i].Equals(columnName, System.StringComparison.OrdinalIgnoreCase))
{
return i;
}
}
return -1;
}
private static void GenerateOrUpdatePrefab(string schemaName, string prefabName, ScriptableObject so, int lineNumber)
{
string prefabOutputPath = Path.Combine(PREFAB_BASE_PATH, schemaName);
if (!Directory.Exists(prefabOutputPath))
{
Directory.CreateDirectory(prefabOutputPath);
}
string prefabPath = Path.Combine(prefabOutputPath, $"{prefabName}.prefab");
IPrefabSetup prefabSetup = GetPrefabSetup(schemaName);
if (prefabSetup == null)
{
Debug.LogWarning($"[CSVImporter] No prefab setup found for {schemaName}, skipping prefab generation");
return;
}
GameObject template = LoadTemplate(schemaName);
if (template == null)
{
Debug.LogWarning($"[CSVImporter] No template found for {schemaName}, skipping prefab generation");
return;
}
if (AssetDatabase.LoadAssetAtPath<GameObject>(prefabPath) != null)
{
UpdateExistingPrefab(prefabPath, so, prefabSetup);
}
else
{
GameObject prefabInstance = GameObject.Instantiate(template);
prefabInstance.name = prefabName;
PrefabUtility.SaveAsPrefabAsset(prefabInstance, prefabPath);
GameObject.DestroyImmediate(prefabInstance);
UpdateExistingPrefab(prefabPath, so, prefabSetup);
Debug.Log($"[CSVImporter] Created prefab: {prefabPath}");
}
AssetDatabase.SaveAssets();
}
private static GameObject LoadTemplate(string schemaName)
{
string templatePath = Path.Combine(TEMPLATE_BASE_PATH, $"{schemaName}Template.prefab");
return AssetDatabase.LoadAssetAtPath<GameObject>(templatePath);
}
private static IPrefabSetup GetPrefabSetup(string schemaName)
{
prefabSetups.TryGetValue(schemaName, out IPrefabSetup setup);
return setup;
}
private static void UpdateExistingPrefab(string prefabPath, ScriptableObject so, IPrefabSetup prefabSetup)
{
GameObject prefabContents = PrefabUtility.LoadPrefabContents(prefabPath);
prefabSetup.SetupPrefab(prefabContents, so);
PrefabUtility.SaveAsPrefabAsset(prefabContents, prefabPath);
GameObject.DestroyImmediate(prefabContents);
}
private static void RemoveOldModel(GameObject prefab)
{
Transform oldModel = prefab.transform.Find("Model");
if (oldModel != null)
{
GameObject.DestroyImmediate(oldModel.gameObject);
}
}
// --- 유틸리티 메서드 (기존과 동일) ---
private static string[] ParseCSVLine(string line)
{