Files
test/Assets/PerfectWorld/Scripts/NPC/NPCBuilder.cs
T
2025-11-11 13:33:27 +07:00

137 lines
4.5 KiB
C#

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<NPCBuilder>
{
[Header("📦 Danh sách prefab NPC đư?c quét t? động")]
[SerializeField] private List<GameObject> modelNPCList = new List<GameObject>();
#if UNITY_EDITOR
[Header("📁 Kéo thư m?c chứa Prefab NPC vào đây")]
[SerializeField] private DefaultAsset npcFolder;
#endif
private Dictionary<string, GameObject> modelNPCDic;
public async Task<GameObject> GetModelByPath(string path)
{
return await AddressableManager.Instance.LoadPrefabAsync(path);
}
#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<GameObject>(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<NamedAnimancerComponent>();
if (animancer == null)
{
animancer = prefabRoot.AddComponent<NamedAnimancerComponent>();
addedComponent++;
}
// 🔹 Clear list hiện t?i (tránh duplicate)
if (animancer.Animations != null)
animancer.Animations = null;
var animator = prefabRoot.GetComponentInChildren<Animator>(true);
if (animator != null && animator.runtimeAnimatorController != null)
{
var controller = animator.runtimeAnimatorController;
var animList = animancer.Animations?.ToList() ?? new List<AnimationClip>();
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
}