Files
test/Assets/PerfectWorld/Scripts/NPC/NPCBuilder.cs
T
2025-10-21 18:34:45 +07:00

149 lines
4.8 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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
}