149 lines
4.8 KiB
C#
149 lines
4.8 KiB
C#
using System.Collections.Generic;
|
||
using System.IO;
|
||
using System.Linq;
|
||
using UnityEngine;
|
||
|
||
#if UNITY_EDITOR
|
||
using UnityEditor;
|
||
using BrewMonster;
|
||
|
||
#endif
|
||
|
||
#if UNITY_EDITOR
|
||
using Animancer; // 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;
|
||
|
||
private void Awake()
|
||
{
|
||
if (modelNPCList == null || modelNPCList.Count == 0)
|
||
{
|
||
Debug.LogError("[NPCBuilder] modelNPCList rỗng – hãy quét lại prefab! " + transform.gameObject.name);
|
||
}
|
||
|
||
modelNPCDic = modelNPCList
|
||
.GroupBy(obj => obj.name)
|
||
.ToDictionary(g => g.Key, g => g.First());
|
||
}
|
||
|
||
public GameObject GetModelByName(string name)
|
||
{
|
||
return modelNPCDic != null && modelNPCDic.TryGetValue(name, out var model)
|
||
? model
|
||
: null;
|
||
}
|
||
|
||
#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
|
||
}
|