| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283 |
- using UnityEngine;
- using System.Collections.Generic;
- using System.Linq;
- public class VillagerManager : MonoBehaviour
- {
- [Header("Villager Settings")]
- public GameObject villagerPrefab;
- public int initialVillagerCount = 5;
- public Transform villagerParent;
- [Header("Spawning")]
- public Vector3 spawnAreaCenter = Vector3.zero;
- public float spawnAreaRadius = 5f;
- private List<Villager> allVillagers = new List<Villager>();
- private List<GameObject> workplaces = new List<GameObject>();
- void SpawnInitialVillagers()
- {
- if (villagerPrefab == null)
- {
- Debug.LogWarning("No villager prefab assigned, creating basic villagers");
- CreateBasicVillagers();
- return;
- }
- for (int i = 0; i < initialVillagerCount; i++)
- {
- Vector3 spawnPos = GetRandomSpawnPosition();
- GameObject villagerObj = Instantiate(villagerPrefab, spawnPos, Quaternion.identity, villagerParent);
- Villager villager = villagerObj.GetComponent<Villager>();
- if (villager != null)
- {
- villager.villagerName = $"Villager {i + 1}";
- allVillagers.Add(villager);
- }
- }
- }
- void CreateBasicVillagers()
- {
- for (int i = 0; i < initialVillagerCount; i++)
- {
- Vector3 spawnPos = GetRandomSpawnPosition();
- // Create basic villager GameObject
- GameObject villagerObj = GameObject.CreatePrimitive(PrimitiveType.Capsule);
- villagerObj.transform.position = spawnPos;
- villagerObj.transform.parent = villagerParent;
- villagerObj.name = $"Villager_{i + 1}";
- villagerObj.tag = "Villager";
- // Add Villager component
- Villager villager = villagerObj.AddComponent<Villager>();
- villager.villagerName = $"Villager {i + 1}";
- // Create selection indicator
- GameObject indicator = GameObject.CreatePrimitive(PrimitiveType.Cylinder);
- indicator.transform.SetParent(villagerObj.transform);
- indicator.transform.localPosition = Vector3.down * 0.6f;
- indicator.transform.localScale = Vector3.one * 1.2f;
- indicator.GetComponent<Renderer>().material.color = Color.yellow;
- indicator.SetActive(false);
- villager.selectionIndicator = indicator;
- // Remove collider from indicator
- Destroy(indicator.GetComponent<Collider>());
- allVillagers.Add(villager);
- }
- }
- Vector3 GetRandomSpawnPosition()
- {
- // Find TownHall position if it exists
- GameObject townHall = GameObject.FindWithTag("TownHall");
- Vector3 townHallPos = townHall != null ? townHall.transform.position : spawnAreaCenter;
- Vector3 spawnPos;
- int attempts = 0;
- do
- {
- // Generate random position around the area
- Vector2 randomCircle = Random.insideUnitCircle * spawnAreaRadius;
- spawnPos = spawnAreaCenter + new Vector3(randomCircle.x, 0, randomCircle.y);
- attempts++;
- // Ensure minimum distance from TownHall (3 units away)
- } while (Vector3.Distance(spawnPos, townHallPos) < 3f && attempts < 20);
- return spawnPos;
- }
- void Start()
- {
- SpawnInitialVillagers();
- FindWorkplaces();
- // Ensure villagers are not inside TownHall after spawning
- StartCoroutine(RepositionVillagersAwayFromTownHall());
- }
- System.Collections.IEnumerator RepositionVillagersAwayFromTownHall()
- {
- // Wait a frame to ensure TownHall is created
- yield return null;
- GameObject townHall = GameObject.FindWithTag("TownHall");
- if (townHall == null) yield break;
- Vector3 townHallPos = townHall.transform.position;
- foreach (var villager in allVillagers)
- {
- if (villager != null && Vector3.Distance(villager.transform.position, townHallPos) < 4f)
- {
- // Move villager to a safe distance from TownHall
- Vector2 randomDirection = Random.insideUnitCircle.normalized;
- Vector3 safePos = townHallPos + new Vector3(randomDirection.x, 0, randomDirection.y) * Random.Range(4f, 7f);
- villager.transform.position = safePos;
- Debug.Log($"Repositioned {villager.villagerName} away from TownHall");
- }
- }
- }
- void FindWorkplaces()
- {
- // Find all workplace objects in the scene
- workplaces.AddRange(GameObject.FindGameObjectsWithTag("Tree"));
- workplaces.AddRange(GameObject.FindGameObjectsWithTag("Stone"));
- workplaces.AddRange(GameObject.FindGameObjectsWithTag("Farm"));
- // Note: ConstructionSite tag not implemented yet
- }
- public GameObject FindWorkplaceForJob(JobType job, Vector3 villagerPosition)
- {
- string targetTag = job switch
- {
- JobType.Woodcutter => "Tree",
- JobType.Stonecutter => "Stone",
- JobType.Farmer => "Farm",
- JobType.Builder => "ConstructionSite",
- _ => null
- };
- if (targetTag == null) return null;
- // Find closest workplace of the appropriate type
- GameObject[] workplaces = GameObject.FindGameObjectsWithTag(targetTag);
- GameObject closest = null;
- float closestDistance = float.MaxValue;
- foreach (var workplace in workplaces)
- {
- // Check if workplace is already occupied
- if (IsWorkplaceOccupied(workplace)) continue;
- float distance = Vector3.Distance(villagerPosition, workplace.transform.position);
- if (distance < closestDistance)
- {
- closestDistance = distance;
- closest = workplace;
- }
- }
- return closest;
- }
- bool IsWorkplaceOccupied(GameObject workplace)
- {
- // Check if any villager is already working at this workplace
- return allVillagers.Any(v => v.targetWorkplace == workplace &&
- (v.state == VillagerState.MovingToWork || v.state == VillagerState.Working));
- }
- public void AssignVillagerToJob(Villager villager, JobType job)
- {
- if (villager != null)
- {
- villager.SetJob(job);
- Debug.Log($"{villager.villagerName} assigned to job: {job}");
- }
- }
- public void AssignVillagerToSpecificWorkplace(Villager villager, JobType job, GameObject specificWorkplace)
- {
- if (villager != null)
- {
- villager.SetJob(job);
- // If it's a resource job, assign the specific workplace
- if (job != JobType.None && specificWorkplace != null)
- {
- villager.AssignToSpecificWorkplace(specificWorkplace);
- }
- Debug.Log($"{villager.villagerName} assigned to {job} at {specificWorkplace?.name}");
- }
- }
- public List<Villager> GetVillagersWithJob(JobType job)
- {
- return allVillagers.Where(v => v.currentJob == job).ToList();
- }
- public List<Villager> GetUnemployedVillagers()
- {
- return allVillagers.Where(v => v.currentJob == JobType.None).ToList();
- }
- public List<Villager> GetAllVillagers()
- {
- return new List<Villager>(allVillagers);
- }
- public Villager GetVillagerByName(string name)
- {
- return allVillagers.FirstOrDefault(v => v.villagerName == name);
- }
- public Dictionary<JobType, int> GetJobCounts()
- {
- var jobCounts = new Dictionary<JobType, int>();
- foreach (JobType job in System.Enum.GetValues(typeof(JobType)))
- {
- jobCounts[job] = allVillagers.Count(v => v.currentJob == job);
- }
- return jobCounts;
- }
- public void RegisterVillager(Villager villager)
- {
- if (!allVillagers.Contains(villager))
- {
- allVillagers.Add(villager);
- }
- }
- public void UnregisterVillager(Villager villager)
- {
- allVillagers.Remove(villager);
- }
- // Called by UI or selection system for drag-and-drop job assignment
- public void HandleJobAssignment(Villager villager, Vector3 dropPosition)
- {
- // Determine job based on drop position (what's under the mouse)
- RaycastHit hit;
- if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out hit))
- {
- JobType newJob = DetermineJobFromHit(hit.collider.gameObject);
- if (newJob != JobType.None)
- {
- AssignVillagerToJob(villager, newJob);
- }
- }
- }
- JobType DetermineJobFromHit(GameObject hitObject)
- {
- return hitObject.tag switch
- {
- "Tree" => JobType.Woodcutter,
- "Stone" => JobType.Stonecutter,
- "Farm" => JobType.Farmer,
- "ConstructionSite" => JobType.Builder,
- _ => JobType.None
- };
- }
- void OnDrawGizmosSelected()
- {
- // Draw spawn area
- Gizmos.color = Color.blue;
- Gizmos.DrawWireSphere(spawnAreaCenter, spawnAreaRadius);
- }
- }
|