AIAgentManager.cs 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. using UnityEngine;
  2. using System.Collections.Generic;
  3. /// <summary>
  4. /// Manages spawning and tracking of AI agents in the maze
  5. /// Supports configurable spawn counts and runtime spawning
  6. /// </summary>
  7. public class AIAgentManager : MonoBehaviour
  8. {
  9. [Header("Agent Spawning")]
  10. [SerializeField] private int initialAgentCount = 10;
  11. [SerializeField] private string agentCharacterType = "Default";
  12. [SerializeField] private float spawnDelay = 0.1f;
  13. [Header("Agent Prefab")]
  14. [SerializeField] private GameObject agentPrefab;
  15. [Header("Visual Settings")]
  16. [SerializeField] private bool showAgentPaths = true;
  17. [SerializeField] private Color agentPathColor = Color.yellow;
  18. [SerializeField] private Material agentMaterial;
  19. private MazeController mazeController;
  20. private List<AIAgent> activeAgents = new();
  21. private int nextAgentId = 0;
  22. private bool isInitialized = false;
  23. void Awake()
  24. {
  25. mazeController = GetComponent<MazeController>();
  26. if (mazeController == null)
  27. {
  28. mazeController = FindAnyObjectByType<MazeController>();
  29. }
  30. }
  31. void Start()
  32. {
  33. if (mazeController == null)
  34. {
  35. Debug.LogError("AIAgentManager: MazeController not found!");
  36. enabled = false;
  37. return;
  38. }
  39. // Create agent prefab if not assigned
  40. if (agentPrefab == null)
  41. {
  42. CreateDefaultAgentPrefab();
  43. }
  44. // Spawn initial agents
  45. StartCoroutine(SpawnAgentsCoroutine(initialAgentCount));
  46. isInitialized = true;
  47. }
  48. /// <summary>
  49. /// Creates a default agent prefab if one isn't assigned
  50. /// </summary>
  51. private void CreateDefaultAgentPrefab()
  52. {
  53. GameObject prefab = new GameObject("AIAgent");
  54. prefab.transform.localScale = new Vector3(0.5f, 0.5f, 0.5f);
  55. // Use 3D collider instead of 2D for 3D environment
  56. var collider = prefab.AddComponent<SphereCollider>();
  57. collider.radius = 0.4f;
  58. // Add mesh renderer with a simple sphere
  59. var meshFilter = prefab.AddComponent<MeshFilter>();
  60. var meshRenderer = prefab.AddComponent<MeshRenderer>();
  61. // Use Unity's built-in sphere primitive mesh
  62. meshFilter.mesh = Resources.GetBuiltinResource<Mesh>("Sphere.fbx");
  63. // Create a cyan material using URP shader (Universal Render Pipeline)
  64. var mat = new Material(Shader.Find("Universal Render Pipeline/Lit"));
  65. if (mat.shader == null)
  66. {
  67. // Fallback to simpler URP shader if Lit is not available
  68. mat = new Material(Shader.Find("Universal Render Pipeline/Simple Lit"));
  69. }
  70. if (mat.shader == null)
  71. {
  72. // Last resort - use Standard shader
  73. mat = new Material(Shader.Find("Standard"));
  74. }
  75. mat.color = Color.cyan;
  76. meshRenderer.material = mat;
  77. prefab.AddComponent<AIAgent>();
  78. agentPrefab = prefab;
  79. }
  80. /// <summary>
  81. /// Spawns agents with delay
  82. /// </summary>
  83. private System.Collections.IEnumerator SpawnAgentsCoroutine(int count)
  84. {
  85. for (int i = 0; i < count; i++)
  86. {
  87. SpawnAgent();
  88. yield return new WaitForSeconds(spawnDelay);
  89. }
  90. }
  91. /// <summary>
  92. /// Spawns a single AI agent
  93. /// </summary>
  94. public AIAgent SpawnAgent()
  95. {
  96. if (agentPrefab == null)
  97. {
  98. Debug.LogError("AIAgentManager: Agent prefab not set!");
  99. return null;
  100. }
  101. GameObject agentGO = Instantiate(agentPrefab);
  102. agentGO.name = $"AIAgent_{agentCharacterType}_{nextAgentId}";
  103. var agent = agentGO.GetComponent<AIAgent>();
  104. if (agent == null)
  105. {
  106. agent = agentGO.AddComponent<AIAgent>();
  107. }
  108. // Set agent properties via reflection or public properties
  109. var idField = typeof(AIAgent).GetField("agentId",
  110. System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
  111. var typeField = typeof(AIAgent).GetField("agentCharacterType",
  112. System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
  113. if (idField != null) idField.SetValue(agent, nextAgentId);
  114. if (typeField != null) typeField.SetValue(agent, agentCharacterType);
  115. activeAgents.Add(agent);
  116. nextAgentId++;
  117. Debug.Log($"Spawned agent {nextAgentId - 1} ({agentCharacterType}). Total agents: {activeAgents.Count}");
  118. return agent;
  119. }
  120. /// <summary>
  121. /// Spawns multiple agents at once
  122. /// </summary>
  123. public void SpawnAgents(int count)
  124. {
  125. StartCoroutine(SpawnAgentsCoroutine(count));
  126. }
  127. /// <summary>
  128. /// Removes and destroys an agent
  129. /// </summary>
  130. public void RemoveAgent(AIAgent agent)
  131. {
  132. if (activeAgents.Remove(agent))
  133. {
  134. Destroy(agent.gameObject);
  135. Debug.Log($"Removed agent {agent.AgentId}. Remaining: {activeAgents.Count}");
  136. }
  137. }
  138. /// <summary>
  139. /// Gets agents of a specific character type
  140. /// </summary>
  141. public List<AIAgent> GetAgentsByType(string characterType)
  142. {
  143. var agents = new List<AIAgent>();
  144. foreach (var agent in activeAgents)
  145. {
  146. if (agent.CharacterType == characterType)
  147. {
  148. agents.Add(agent);
  149. }
  150. }
  151. return agents;
  152. }
  153. /// <summary>
  154. /// Gets the count of active agents
  155. /// </summary>
  156. public int GetAgentCount()
  157. {
  158. return activeAgents.Count;
  159. }
  160. /// <summary>
  161. /// Gets agent count by character type
  162. /// </summary>
  163. public int GetAgentCountByType(string characterType)
  164. {
  165. return GetAgentsByType(characterType).Count;
  166. }
  167. /// <summary>
  168. /// Clears all agents and resets
  169. /// </summary>
  170. public void ClearAllAgents()
  171. {
  172. foreach (var agent in activeAgents)
  173. {
  174. Destroy(agent.gameObject);
  175. }
  176. activeAgents.Clear();
  177. nextAgentId = 0;
  178. AIRoomMemoryManager.ClearAllMemories();
  179. }
  180. /// <summary>
  181. /// Resets agents for a new maze
  182. /// </summary>
  183. public void ResetForNewMaze()
  184. {
  185. ClearAllAgents();
  186. if (isInitialized)
  187. {
  188. StartCoroutine(SpawnAgentsCoroutine(initialAgentCount));
  189. }
  190. }
  191. /// <summary>
  192. /// Gets UI info about agents
  193. /// </summary>
  194. public string GetAgentStats()
  195. {
  196. int total = activeAgents.Count;
  197. string stats = $"Total Agents: {total}\n";
  198. var typeGroups = new Dictionary<string, int>();
  199. foreach (var agent in activeAgents)
  200. {
  201. if (!typeGroups.ContainsKey(agent.CharacterType))
  202. {
  203. typeGroups[agent.CharacterType] = 0;
  204. }
  205. typeGroups[agent.CharacterType]++;
  206. }
  207. foreach (var kvp in typeGroups)
  208. {
  209. var memory = AIRoomMemoryManager.GetMemory(kvp.Key);
  210. stats += $"{kvp.Key}: {kvp.Value} agents, {memory.VisitedCount} rooms explored\n";
  211. }
  212. return stats;
  213. }
  214. /// <summary>
  215. /// Gets the initial agent count setting
  216. /// </summary>
  217. public int InitialAgentCount => initialAgentCount;
  218. /// <summary>
  219. /// Sets the initial agent count (affects next reset)
  220. /// </summary>
  221. public void SetInitialAgentCount(int count)
  222. {
  223. initialAgentCount = count;
  224. }
  225. /// <summary>
  226. /// Gets the count of active agents
  227. /// </summary>
  228. public int GetActiveAgentCount()
  229. {
  230. return activeAgents.Count;
  231. }
  232. /// <summary>
  233. /// Gets the list of active agents
  234. /// </summary>
  235. public List<AIAgent> GetActiveAgents()
  236. {
  237. return activeAgents;
  238. }
  239. }