using UnityEngine; using UnityEngine.UIElements; public class SceneSetup : MonoBehaviour { [Header("Scene Setup")] public bool setupSceneOnStart = true; public Vector3 townHallPosition = Vector3.zero; public int numberOfTrees = 5; public int numberOfStones = 3; // Farms will be built by players, not pre-generated public float resourceSpawnRadius = 15f; [Header("Materials (Optional)")] public Material villagerMaterial; public Material townHallMaterial; public Material treeMaterial; public Material stoneMaterial; public Material farmMaterial; void Start() { if (setupSceneOnStart) { SetupScene(); } } [ContextMenu("Setup Scene")] public void SetupScene() { CreateGround(); CreateTownHall(); CreateResourceNodes(); SetupCamera(); CreateGameManager(); } void CreateGround() { GameObject ground = GameObject.Find("Ground"); if (ground == null) { // Create ground plane ground = GameObject.CreatePrimitive(PrimitiveType.Plane); ground.name = "Ground"; ground.transform.position = Vector3.zero; ground.transform.localScale = new Vector3(5f, 1f, 5f); // 50x50 units // Set material if available Renderer groundRenderer = ground.GetComponent(); if (groundRenderer != null) { groundRenderer.material.color = new Color(0.3f, 0.5f, 0.3f); // Green ground } Debug.Log("Created ground plane"); } } void CreateTownHall() { GameObject townHallGO = GameObject.FindWithTag("TownHall"); if (townHallGO == null) { // Create TownHall townHallGO = GameObject.CreatePrimitive(PrimitiveType.Cube); townHallGO.name = "TownHall"; townHallGO.tag = "TownHall"; townHallGO.transform.position = townHallPosition; townHallGO.transform.localScale = new Vector3(3f, 2f, 3f); // Add TownHall component TownHall townHall = townHallGO.AddComponent(); // Apply material if available if (townHallMaterial != null) { townHallGO.GetComponent().material = townHallMaterial; } else { townHallGO.GetComponent().material.color = Color.blue; } // Create selection indicator GameObject indicator = GameObject.CreatePrimitive(PrimitiveType.Cylinder); indicator.transform.SetParent(townHallGO.transform); indicator.transform.localPosition = Vector3.down * 1.2f; indicator.transform.localScale = Vector3.one * 1.5f; indicator.GetComponent().material.color = Color.yellow; indicator.SetActive(false); townHall.selectionIndicator = indicator; Destroy(indicator.GetComponent()); Debug.Log("Created TownHall"); } } void CreateForests() { int numForestClusters = Random.Range(2, 5); // 2-4 forest clusters for (int cluster = 0; cluster < numForestClusters; cluster++) { // Pick a random center point for this forest cluster Vector3 clusterCenter = GetRandomPosition(); // Create 3-7 trees in this cluster int treesInCluster = Random.Range(3, 8); for (int i = 0; i < treesInCluster; i++) { // Position trees within cluster radius Vector3 offset = Random.insideUnitSphere * 8f; // 8 unit radius offset.y = 0; // Keep on ground level Vector3 treePosition = clusterCenter + offset; // Make sure it's within bounds treePosition.x = Mathf.Clamp(treePosition.x, -resourceSpawnRadius + 2, resourceSpawnRadius - 2); treePosition.z = Mathf.Clamp(treePosition.z, -resourceSpawnRadius + 2, resourceSpawnRadius - 2); CreateTree(treePosition, cluster * 10 + i); } } // Add some scattered individual trees (about 30% of cluster trees) int scatteredTrees = (numForestClusters * 5) / 3; // Roughly 30% extra for (int i = 0; i < scatteredTrees; i++) { Vector3 position = GetRandomPosition(); CreateTree(position, 1000 + i); // Use high IDs to avoid conflicts } Debug.Log($"Created {numForestClusters} forest clusters with scattered trees"); } void CreateResourceNodes() { // Create Trees in forest-like clusters CreateForests(); // Create Stones in clusters int numStoneClusters = Random.Range(2, 4); // 2-3 stone clusters for (int cluster = 0; cluster < numStoneClusters; cluster++) { Vector3 clusterCenter = GetRandomPosition(); // Create 3-5 stones in this cluster int stonesInCluster = Random.Range(3, 6); for (int i = 0; i < stonesInCluster; i++) { Vector3 offset = Random.insideUnitSphere * 3f; // 3 unit radius for tighter clusters offset.y = 0; Vector3 stonePosition = clusterCenter + offset; stonePosition.x = Mathf.Clamp(stonePosition.x, -resourceSpawnRadius + 2, resourceSpawnRadius - 2); stonePosition.z = Mathf.Clamp(stonePosition.z, -resourceSpawnRadius + 2, resourceSpawnRadius - 2); CreateStone(stonePosition, cluster * 10 + i); } } Debug.Log($"Created {numStoneClusters} stone clusters"); // No longer create pre-made farms - farmhouses will be built by players } void CreateTree(Vector3 position, int index) { GameObject tree = GameObject.CreatePrimitive(PrimitiveType.Cylinder); tree.name = $"Tree_{index + 1}"; tree.tag = "Tree"; tree.transform.position = position; tree.transform.localScale = new Vector3(1f, 2f, 1f); // Add ResourceNode component ResourceNode node = tree.AddComponent(); node.nodeType = ResourceNodeType.Tree; node.resourceType = ResourceType.Wood; node.maxResources = Random.Range(40, 70); // Variable wood amounts node.currentResources = node.maxResources; node.regenerationRate = 0f; // Trees don't regenerate node.nodeRenderer = tree.GetComponent(); // Apply material if (treeMaterial != null) { tree.GetComponent().material = treeMaterial; } else { tree.GetComponent().material.color = Color.green; } // Create selection indicator CreateSelectionIndicator(tree, node); Debug.Log($"Created Tree at {position}"); } void CreateStone(Vector3 position, int index) { // Create stone cluster with multiple rocks GameObject stoneCluster = new GameObject($"StoneCluster_{index + 1}"); stoneCluster.tag = "Stone"; stoneCluster.transform.position = position; // Main large stone with random size and position jitter GameObject mainStone = GameObject.CreatePrimitive(PrimitiveType.Sphere); mainStone.name = "MainStone"; mainStone.transform.SetParent(stoneCluster.transform); mainStone.transform.localPosition = new Vector3( Random.Range(-0.2f, 0.2f), Random.Range(-0.1f, 0.1f), Random.Range(-0.2f, 0.2f) ); mainStone.transform.localScale = Vector3.one * Random.Range(1.3f, 1.8f); mainStone.transform.rotation = Random.rotation; // Add 2-5 smaller stones with more varied positioning int smallStones = Random.Range(2, 6); for (int i = 0; i < smallStones; i++) { GameObject smallStone = GameObject.CreatePrimitive(PrimitiveType.Sphere); smallStone.name = $"SmallStone_{i}"; smallStone.transform.SetParent(stoneCluster.transform); // More random angle distribution instead of even spacing float angle = Random.Range(0f, 360f); float distance = Random.Range(0.6f, 1.4f); Vector3 offset = new Vector3( Mathf.Cos(angle * Mathf.Deg2Rad) * distance, Random.Range(-0.3f, 0.2f), Mathf.Sin(angle * Mathf.Deg2Rad) * distance ); smallStone.transform.localPosition = offset; smallStone.transform.localScale = Vector3.one * Random.Range(0.5f, 1.1f); smallStone.transform.rotation = Random.rotation; // Remove collider so only parent cluster is selectable Collider smallCollider = smallStone.GetComponent(); if (smallCollider != null) Destroy(smallCollider); Renderer smallRenderer = smallStone.GetComponent(); if (stoneMaterial != null) smallRenderer.material = stoneMaterial; else smallRenderer.material.color = Color.gray; } // Add ResourceNode component to parent ResourceNode node = stoneCluster.AddComponent(); node.nodeType = ResourceNodeType.Stone; node.resourceType = ResourceType.Stone; node.maxResources = Random.Range(60, 100); // Variable stone amounts node.currentResources = node.maxResources; node.regenerationRate = 0f; // Stones don't regenerate node.nodeRenderer = mainStone.GetComponent(); // Set material if (stoneMaterial != null) node.nodeRenderer.material = stoneMaterial; else node.nodeRenderer.material.color = Color.gray; // Add collider to parent for clicking BoxCollider clusterCollider = stoneCluster.AddComponent(); clusterCollider.size = new Vector3(3f, 2f, 3f); clusterCollider.center = Vector3.up * 0.5f; // Create selection indicator CreateSelectionIndicator(stoneCluster, node); Debug.Log($"Created Stone Cluster at {position} with {node.maxResources} stone"); } void CreateFarm(Vector3 position, int index) { GameObject farm = GameObject.CreatePrimitive(PrimitiveType.Cube); farm.name = $"Farm_{index + 1}"; farm.tag = "Farm"; farm.transform.position = position; farm.transform.localScale = new Vector3(2f, 0.2f, 2f); // Add ResourceNode component ResourceNode node = farm.AddComponent(); node.nodeType = ResourceNodeType.Farm; node.resourceType = ResourceType.Food; node.maxResources = 100; node.currentResources = 100; node.regenerationRate = 3f; // Apply material if (farmMaterial != null) { farm.GetComponent().material = farmMaterial; } else { farm.GetComponent().material.color = Color.yellow; } // Create selection indicator CreateSelectionIndicator(farm, node); Debug.Log($"Created Farm at {position}"); } void CreateSelectionIndicator(GameObject parent, ResourceNode node) { GameObject indicator = GameObject.CreatePrimitive(PrimitiveType.Cylinder); indicator.transform.SetParent(parent.transform); indicator.transform.localPosition = Vector3.down * 0.6f; indicator.transform.localScale = Vector3.one * 1.2f; indicator.GetComponent().material.color = Color.cyan; indicator.SetActive(false); node.selectionIndicator = indicator; Destroy(indicator.GetComponent()); } Vector3 GetRandomPosition() { Vector2 randomCircle = Random.insideUnitCircle * resourceSpawnRadius; Vector3 position = townHallPosition + new Vector3(randomCircle.x, 0, randomCircle.y); // Make sure we don't spawn too close to town hall if (Vector3.Distance(position, townHallPosition) < 3f) { return GetRandomPosition(); // Try again } return position; } void SetupCamera() { Camera mainCamera = Camera.main; if (mainCamera == null) { mainCamera = FindFirstObjectByType(); } if (mainCamera != null) { // Position camera above the scene mainCamera.transform.position = new Vector3(0, 15, -10); mainCamera.transform.rotation = Quaternion.Euler(45, 0, 0); // Add camera controller if it doesn't exist CameraController cameraController = mainCamera.GetComponent(); if (cameraController == null) { cameraController = mainCamera.gameObject.AddComponent(); } // Set up camera for orthographic view (better for RTS games) mainCamera.orthographic = true; mainCamera.orthographicSize = 15f; Debug.Log("Camera setup complete"); } } void CreateGameManager() { // Check if GameManager already exists GameManager existingGameManager = FindFirstObjectByType(); if (existingGameManager == null) { GameObject gameManagerGO = new GameObject("GameManager"); // Add GameManager component GameManager gameManager = gameManagerGO.AddComponent(); Debug.Log("Created GameManager"); } // Create separate UI GameObject if it doesn't exist GameObject uiGameObject = GameObject.Find("UI"); if (uiGameObject == null) { uiGameObject = new GameObject("UI"); uiGameObject.transform.position = Vector3.zero; // Add UIDocument component UIDocument uiDoc = uiGameObject.AddComponent(); // Try to load the UXML file from Resources folder VisualTreeAsset gameUIAsset = Resources.Load("GameUI"); if (gameUIAsset != null) { uiDoc.visualTreeAsset = gameUIAsset; Debug.Log($"Assigned UXML asset '{gameUIAsset.name}' to UIDocument"); } else { Debug.LogWarning("Could not find GameUI.uxml in Resources! Please assign it manually in the inspector."); } // Try to load panel settings PanelSettings panelSettings = Resources.Load("PanelSettings"); if (panelSettings != null) { uiDoc.panelSettings = panelSettings; Debug.Log("Assigned PanelSettings to UIDocument"); } // Add GameUI component uiGameObject.AddComponent(); Debug.Log("Created UI GameObject with GameUI component"); } // Create Building System GameObject GameObject buildingSystemGO = GameObject.Find("BuildingSystem"); if (buildingSystemGO == null) { buildingSystemGO = new GameObject("BuildingSystem"); buildingSystemGO.AddComponent(); buildingSystemGO.AddComponent(); Debug.Log("Created BuildingSystem and HousingManager"); } } [ContextMenu("Clear Scene")] public void ClearScene() { // Clear existing objects (useful for testing) GameObject[] trees = GameObject.FindGameObjectsWithTag("Tree"); GameObject[] stones = GameObject.FindGameObjectsWithTag("Stone"); GameObject[] farms = GameObject.FindGameObjectsWithTag("Farm"); GameObject[] villagers = GameObject.FindGameObjectsWithTag("Villager"); GameObject townHall = GameObject.FindWithTag("TownHall"); foreach (var obj in trees) DestroyImmediate(obj); foreach (var obj in stones) DestroyImmediate(obj); foreach (var obj in farms) DestroyImmediate(obj); foreach (var obj in villagers) DestroyImmediate(obj); if (townHall != null) DestroyImmediate(townHall); Debug.Log("Scene cleared"); } }