using System.Collections.Generic; using System.Linq; using UnityEngine; #if UNITY_EDITOR using UnityEditor; #endif using BrewMonster; // #if UNITY_EDITOR using Animancer; using BrewMonster.Scripts; using System.Threading.Tasks; // B�?o đ�?m b�?n có Animancer package // #endif public class NPCBuilder : MonoSingleton { [Header("📦 Danh sách prefab NPC đư�?c quét t�? động")] [SerializeField] private List modelNPCList = new List(); #if UNITY_EDITOR [Header("📁 Kéo thư m�?c chứa Prefab NPC vào đây")] [SerializeField] private DefaultAsset npcFolder; #endif private Dictionary modelNPCDic; public async Task GetModelByPath(string path) { //return await AddressableManager.Instance.LoadPrefabAsync(AFile.NormalizePath(path)); return await PoolManager.Instance.SpawnAsync(AFile.NormalizePath(path), Vector3.zero, Quaternion.identity, memoryReleaseTTL: 0f, autoDespawnTime: 0f); } #if UNITY_EDITOR // -------------------------- // 📌 ContextMenu 1: Quét Prefab // -------------------------- [ContextMenu("🔄 Quét Prefab trong thư m�?c")] private void ScanPrefabsInFolder() { modelNPCList.Clear(); if (npcFolder == null) { Debug.LogWarning("[NPCBuilder] Vui lòng kéo thư m�?c Prefab NPC vào trường npcFolder."); return; } string folderPath = AssetDatabase.GetAssetPath(npcFolder); if (!AssetDatabase.IsValidFolder(folderPath)) { Debug.LogWarning("[NPCBuilder] Thư m�?c không h�?p l�?."); return; } string[] prefabGUIDs = AssetDatabase.FindAssets("t:Prefab", new[] { folderPath }); foreach (string guid in prefabGUIDs) { string assetPath = AssetDatabase.GUIDToAssetPath(guid); GameObject prefab = AssetDatabase.LoadAssetAtPath(assetPath); if (prefab != null) { modelNPCList.Add(prefab); } } modelNPCList = modelNPCList .GroupBy(obj => obj.name) .Select(g => g.First()) .ToList(); EditorUtility.SetDirty(this); AssetDatabase.SaveAssets(); Debug.Log($"[NPCBuilder] �? Đã quét {modelNPCList.Count} prefab t�? {folderPath}"); } // -------------------------- // 📌 ContextMenu 2: Thêm NamedAnimancerComponent & Animation Clip // -------------------------- [ContextMenu("🎬 Đ�?m b�?o Prefab có NamedAnimancerComponent và Add Animations")] private void EnsureNamedAnimancerAndAddAnimations() { int processed = 0; int addedComponent = 0; int totalClips = 0; foreach (var prefab in modelNPCList) { if (prefab == null) continue; string path = AssetDatabase.GetAssetPath(prefab); if (string.IsNullOrEmpty(path)) continue; GameObject prefabRoot = PrefabUtility.LoadPrefabContents(path); var animancer = prefabRoot.GetComponent(); if (animancer == null) { animancer = prefabRoot.AddComponent(); addedComponent++; } // 🔹 Clear list hiện t�?i (tránh duplicate) if (animancer.Animations != null) animancer.Animations = null; var animator = prefabRoot.GetComponentInChildren(true); if (animator != null && animator.runtimeAnimatorController != null) { var controller = animator.runtimeAnimatorController; var animList = animancer.Animations?.ToList() ?? new List(); foreach (var clip in controller.animationClips) { if (clip == null) continue; animList.Add(clip); totalClips++; } animancer.Animations = animList.ToArray(); } else { Debug.LogWarning($"[NPCBuilder] ⚠️ Prefab {prefab.name} không có Animator hoặc Controller!"); } // Ghi đè l�?i prefab PrefabUtility.SaveAsPrefabAsset(prefabRoot, path); PrefabUtility.UnloadPrefabContents(prefabRoot); processed++; } AssetDatabase.SaveAssets(); Debug.Log($"[NPCBuilder] �? Đã x�? lý {processed} prefab. Thêm mới {addedComponent} component, tổng {totalClips} clip animation đư�?c ghi l�?i."); } #endif }