using System; using System.Collections.Generic; using UnityEngine; public class SpawnController : MonoBehaviour { private Dictionary _enemyDatas; private Dictionary _prototypes = new Dictionary(); private readonly List _spawned = new(); [SerializeField] private string _enemyPrefabPath; // 스폰할 프리팹 [SerializeField] private string _enemyDataPath; // 스폰할 프리팹 [SerializeField] private LayerMask _spawnedTargetLayers; // 스포너 Inspector에서 설정 [SerializeField] private LayerMask _spawnedObstacleLayers; // 스포너 Inspector에서 설정 private Transform _prototypeRoot; // 계층 관리용 int monsterCount = 0; public string EnemyPrefabPath { get { return _enemyPrefabPath; } set { _enemyPrefabPath = value; }} public string EnemyDataPath { get { return _enemyDataPath; } set { _enemyDataPath = value; }} void Awake() { var root = new GameObject("EnemyPrototypes"); root.SetActive(false); _prototypeRoot = root.transform; } private void Start() { if (string.IsNullOrEmpty(EnemyPrefabPath) || string.IsNullOrEmpty(EnemyDataPath)) throw new ArgumentNullException("EnemyPrefabPath or EnemyDataPath is null or empty"); _enemyDatas = Manager.Data.LoadToDict(EnemyDataPath, (enemy) => enemy.name); CreateEnemyPrototype(); } void Update() { float radius = 2.0f; for (; monsterCount < 5; monsterCount++) { float angle = monsterCount * Mathf.PI * 2 / 5; Vector3 pos = new Vector3(Mathf.Cos(angle), 0, Mathf.Sin(angle)) * radius + new Vector3(0, 0, 10); SpawnFromProtoType("Test_Enemy_1", pos); } } void CreateEnemyPrototype() { foreach (var enemyData in _enemyDatas) { string key = enemyData.Key; EnemyData data = enemyData.Value; GameObject enemy = Manager.Resource.Instantiate(EnemyPrefabPath); enemy.name = $"{key}_Prototype"; enemy.transform.SetParent(_prototypeRoot, worldPositionStays: false); enemy.SetActive(false); if(!enemy.TryGetComponent(out _)) enemy.AddComponent(); var status = enemy.GetComponent(); if (status == null) status = enemy.AddComponent(); status.Data = data.status; // status = data.status; // status.CopyFrom(statusData); _prototypes[key] = enemy; } } public GameObject SpawnFromProtoType(string key, Vector3 position, Quaternion? rotation = null) { if(!_prototypes.TryGetValue(key, out GameObject prototype)|| prototype == null) { Debug.LogError($"SpawnFromProtoType Failed! : {key}"); return null; } var rot = rotation ?? Quaternion.identity; GameObject clone = Instantiate(prototype, position, rot); clone.name = $"{key}"; clone.SetActive(true); _spawned.Add(clone); return clone; } // 오버로드: 회전 생략 // public GameObject SpawnFromPrototype(string key, Vector3 position) => SpawnFromPrototype(key, position, null); public void Despawn(GameObject go) { if (go == null) return; _spawned.Remove(go); Destroy(go); } public void DespawnAll() { for (int i = _spawned.Count - 1; i >= 0; i--) { Despawn(_spawned[i]); } _spawned.Clear(); } // private static void CopyStatusValues(Status_Enemy src, Status_Enemy dst) // { // if (src == null || dst == null) return; // // var type = typeof(Status_Enemy); // // foreach (var f in type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) // { // if (f.IsInitOnly || f.IsLiteral) continue; // if (typeof(Delegate).IsAssignableFrom(f.FieldType)) continue; // f.SetValue(dst, f.GetValue(src)); // } // // foreach (var p in type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) // { // if (!p.CanRead || !p.CanWrite) continue; // if (p.GetIndexParameters().Length > 0) continue; // try { p.SetValue(dst, p.GetValue(src)); } catch { } // } // } }