// Do your threaded task. DON'T use the Unity API here protected override void ThreadFunction() { /* * I could of split each type of generation into their own methods, but I just used regions instead :/ */ //The C# Random instance Random rnd = new Random(seed); //Set the size of the whole city citySlots = new GeneratedSlot[citySize, citySize]; //Setting the list roads = new List <Road>(); //Setting all the tiles first so we don't get any errors later on EmptySlot emptySlot = new EmptySlot(); for (int x = 0; x < citySize; x++) { for (int y = 0; y < citySize; y++) { citySlots[x, y] = emptySlot; } } #region Motorway /* * * Motorway * */ //Generate the one motorway from top to bottom int motorwayStartX = 20 + rnd.Next(citySize - 40); //Picks a random number from 0 to city size //The motorway is always going to be the size of the city Vector3[] points = new Vector3[citySize]; //The first slot won't be connected to anything citySlots[motorwayStartX, 0] = new RoadSlot(RoadSlot.Type.M, 0); points[0] = new Vector3(motorwayStartX, 0, 0); //This for loop will go from top to bottom along the one x axis to create the motorway for (int i = 1; i < citySize; i++) { citySlots[motorwayStartX, i] = new RoadSlot(RoadSlot.Type.M, 0); points[i] = new Vector3(motorwayStartX, 0, i); } Road motorway = new Road(points, RoadType.M); roads.Add(motorway); #endregion #region A-Road /* * * A-Road * * Each side of the motorway there will be 3 different A roads unless * the motorway is less that the minium size for small houses */ //Left side Vector3[] a1Points = new Vector3[motorwayStartX]; Vector3[] a2Points = new Vector3[motorwayStartX]; Vector3[] a3Points = new Vector3[motorwayStartX]; //Right side Vector3[] a4Points = new Vector3[citySize - motorwayStartX]; Vector3[] a5Points = new Vector3[citySize - motorwayStartX]; Vector3[] a6Points = new Vector3[citySize - motorwayStartX]; for (int i = 0; i < motorwayStartX; i++) { CheckSlotForRoad(motorwayStartX - i, 0, 0, 0, RoadSlot.Type.A, RoadSlot.Type.A, 90); a1Points[i] = new Vector3(motorwayStartX - i, 0, 0); CheckSlotForRoad(motorwayStartX - i, citySize / 2, 0, 0, RoadSlot.Type.A, RoadSlot.Type.A, 90); a2Points[i] = new Vector3(motorwayStartX - i, 0, citySize / 2); CheckSlotForRoad(motorwayStartX - i, citySize - 1, 0, 0, RoadSlot.Type.A, RoadSlot.Type.A, 90); a3Points[i] = new Vector3(motorwayStartX - i, 0, citySize - 1); } for (int i = 0; i < citySize - motorwayStartX; i++) { CheckSlotForRoad(motorwayStartX + i, 0, 0, 0, RoadSlot.Type.A, RoadSlot.Type.A, 90); a4Points[i] = new Vector3(motorwayStartX + i, 0, 0); CheckSlotForRoad(motorwayStartX + i, citySize / 2, 0, 0, RoadSlot.Type.A, RoadSlot.Type.A, 90); a5Points[i] = new Vector3(motorwayStartX + i, 0, citySize / 2); CheckSlotForRoad(motorwayStartX + i, citySize - 1, 0, 0, RoadSlot.Type.A, RoadSlot.Type.A, 90); a6Points[i] = new Vector3(motorwayStartX + i, 0, citySize - 1); } Road a1 = new Road(a1Points, RoadType.A); Road a2 = new Road(a2Points, RoadType.A); Road a3 = new Road(a3Points, RoadType.A); Road a4 = new Road(a4Points, RoadType.A); Road a5 = new Road(a5Points, RoadType.A); Road a6 = new Road(a6Points, RoadType.A); roads.Add(a1); roads.Add(a2); roads.Add(a3); roads.Add(a4); roads.Add(a5); roads.Add(a6); #endregion #region S-Road Housing /* * * Side Road Housing * * */ //These two roads are the roads we are going to be finding the random points off of Road leftStraightRoad = a1; Road rightStraightRoad = a4; int amountOfSideRoads = rnd.Next(0, 5); //This number will be used to how many random points we find for (int i = 0; i < (citySize / 2) - 2; i += 2) { Vector3[] leftRoadPoints = new Vector3[motorwayStartX - 2]; //There is some overflow here, not sure why Vector3[] rightRoadPoints = new Vector3[citySize - motorwayStartX - 2]; Vector2[] leftRandomPoints = new Vector2[amountOfSideRoads]; Vector2[] rightRandomPoints = new Vector2[amountOfSideRoads]; //First find the random points that we want to use for (int j = 0; j < amountOfSideRoads; j++) { //This will give a random point of the points list to pick from int leftPoint = rnd.Next(leftStraightRoad.points.Length - 1); int rightPoint = rnd.Next(rightStraightRoad.points.Length - 1); Vector2 leftVector2 = leftStraightRoad.points[leftPoint + 1]; Vector2 rightVector2 = rightStraightRoad.points[rightPoint + 1]; leftRandomPoints[j] = leftVector2; rightRandomPoints[j] = rightVector2; } //Loop for the whole length that the road needs to be for (int j = 0; j < citySize - motorwayStartX - 2; j++) { int x = motorwayStartX + j + 2; int y = i + 2; RoadSlot rightSlot = new RoadSlot(RoadSlot.Type.S, 90); rightRoadPoints[j] = new Vector3(x, 0, y); for (int k = 0; k < rightRandomPoints.Length; k++) { if (rightRandomPoints[k].x == x) { rightSlot.AddConnection(x, y - 1, RoadSlot.Type.S); //There should be the road we had done before in this slot, so we are just adding a connection CheckSlotForRoad(x, i, x, i + 1, RoadSlot.Type.S, RoadSlot.Type.S, 90); RoadSlot middleSlot = new RoadSlot(RoadSlot.Type.S, 0); citySlots[x, y - 1] = middleSlot; Vector3[] smallRoadPoints = new Vector3[3]; smallRoadPoints[0] = new Vector3(x, 0, y); smallRoadPoints[1] = new Vector3(x, 0, y - 1); smallRoadPoints[2] = new Vector3(x, 0, i); roads.Add(new Road(smallRoadPoints, RoadType.S)); //Rotating the bottom S road if (citySlots[x, i] is RoadSlot) { if (((RoadSlot)citySlots[x, i]).type == RoadSlot.Type.S) { ((RoadSlot)citySlots[x, i]).primaryDirection += 180; } } break; } else { //If there is no road joining the two straight lines, this should be a building citySlots[x, y - 1] = new BuildingSlot(); } } citySlots[x, y] = rightSlot; } for (int j = 0; j < motorwayStartX - 2; j++) { int x = motorwayStartX - j - 2; int y = i + 2; RoadSlot leftSlot = new RoadSlot(RoadSlot.Type.S, 90); leftRoadPoints[j] = new Vector3(x, 0, y); for (int k = 0; k < leftRandomPoints.Length; k++) { if (leftRandomPoints[k].x == x) { leftSlot.AddConnection(x, y - 1, RoadSlot.Type.S); //There should be the road we had done before in this slot, so we are just adding a connection CheckSlotForRoad(x, i, x, i + 1, RoadSlot.Type.S, RoadSlot.Type.S, 90); RoadSlot middleSlot = new RoadSlot(RoadSlot.Type.S, 0); citySlots[x, y - 1] = middleSlot; Vector3[] smallRoadPoints = new Vector3[3]; smallRoadPoints[0] = new Vector3(x, 0, y); smallRoadPoints[1] = new Vector3(x, 0, y - 1); smallRoadPoints[2] = new Vector3(x, 0, i); roads.Add(new Road(smallRoadPoints, RoadType.S)); //Rotating the bottom S road if (citySlots[x, i] is RoadSlot) { if (((RoadSlot)citySlots[x, i]).type == RoadSlot.Type.S) { ((RoadSlot)citySlots[x, i]).primaryDirection += 180; } } break; } else { //If there is no road joining the two straight lines, this should be a building citySlots[x, y - 1] = new BuildingSlot(); } } citySlots[x, y] = leftSlot; } Road left = new Road(leftRoadPoints, RoadType.S); Road right = new Road(rightRoadPoints, RoadType.S); leftStraightRoad = left; rightStraightRoad = right; roads.Add(left); roads.Add(right); } //Connecting the the middle A roads Vector2[] leftLastRandomPoints = new Vector2[amountOfSideRoads]; Vector2[] rightLastRandomPoints = new Vector2[amountOfSideRoads]; for (int i = 0; i < amountOfSideRoads; i++) { Vector3[] leftPoints = new Vector3[3]; Vector3[] rightPoints = new Vector3[3]; //This will give a random point of the points list to pick from int leftPoint = rnd.Next(leftStraightRoad.points.Length); int rightPoint = rnd.Next(rightStraightRoad.points.Length); leftPoints[0] = new Vector3(leftStraightRoad.points[leftPoint].x, 0, (citySize / 2) - 2); leftPoints[1] = new Vector3(leftStraightRoad.points[leftPoint].x, 0, (citySize / 2)); leftPoints[2] = new Vector3(leftStraightRoad.points[leftPoint].x, 0, (citySize / 2)); rightPoints[0] = new Vector3(rightStraightRoad.points[rightPoint].x, 0, (citySize / 2) - 2); rightPoints[1] = new Vector3(rightStraightRoad.points[rightPoint].x, 0, (citySize / 2) - 1); rightPoints[2] = new Vector3(rightStraightRoad.points[rightPoint].x, 0, (citySize / 2)); //These float should already be a whole number anyways int rightX = Mathf.RoundToInt(rightPoints[0].x); int leftX = Mathf.RoundToInt(leftPoints[0].x); int y = Mathf.RoundToInt(leftStraightRoad.points[0].z); //Adding it to the slot array CheckSlotForRoad(rightX, y, rightX, y + 1, RoadSlot.Type.S, RoadSlot.Type.S, 180); CheckSlotForRoad(rightX, y + 1, 0, 0, RoadSlot.Type.S, RoadSlot.Type.S, 0); CheckSlotForRoad(rightX, y + 2, rightX, y + 1, RoadSlot.Type.S, RoadSlot.Type.S, 180); CheckSlotForRoad(leftX, y, leftX, y + 1, RoadSlot.Type.S, RoadSlot.Type.S, 180); CheckSlotForRoad(leftX, y + 1, 0, 0, RoadSlot.Type.S, RoadSlot.Type.S, 0); CheckSlotForRoad(leftX, y + 2, leftX, y + 1, RoadSlot.Type.S, RoadSlot.Type.S, 180); //Having to do some manual correction as CheckSlotsForRoad has a flaw ((RoadSlot)citySlots[leftX, y]).primaryDirection = 270; ((RoadSlot)citySlots[leftX, y + 2]).primaryDirection = 270; ((RoadSlot)citySlots[rightX, y]).primaryDirection = 270; ((RoadSlot)citySlots[rightX, y + 2]).primaryDirection = 270; Road leftSmallRoad = new Road(leftPoints, RoadType.S); Road rightSmallRoad = new Road(rightPoints, RoadType.S); roads.Add(leftSmallRoad); roads.Add(rightSmallRoad); } #endregion #region S-Road Factories /* * * S-Road Factories * * The way the roads are going to generate will be based of a fixed size * So for every 10 units, we place a road then inside of that 10 units we would spawn the prefab for the factory * if there is less that 10 units left we just stop * * If there is less than 10 units on the whole side we just leave that side. */ //First we want to work out how many times we can move along on one side // float factorySize = 4; int leftFactoryRoads = Mathf.FloorToInt(motorwayStartX / factorySize); int rightFactoryRoads = Mathf.FloorToInt((citySize - motorwayStartX) / factorySize); citySlots[motorwayStartX + 1, (citySize / 2) + 1] = new FactorySlot(true, true); citySlots[motorwayStartX - 1, (citySize / 2) + 1] = new FactorySlot(true, false); //Left side for (int i = 1; i <= leftFactoryRoads; i++) { int roadX = Mathf.RoundToInt(motorwayStartX - (factorySize * i)); int distance = citySize / 2 - 2; //For the distance between the middle road and the top road, we create a straight line on x Vector3[] currentRoadPoints = new Vector3[distance]; //This should be half the size CheckSlotForRoad(roadX, citySize / 2, roadX, citySize / 2, RoadSlot.Type.S, RoadSlot.Type.S, 0); for (int j = 0; j < distance; j++) { int y = j + citySize / 2 + 1; currentRoadPoints[j] = new Vector3(roadX, 0, y); citySlots[roadX, y] = new RoadSlot(RoadSlot.Type.S, 0); //Every 4 if (j % 2 == 0 && roadX - 1 > 0) { //Adding the factory spawn citySlots[roadX - 1, y] = new FactorySlot(true, false); } } Road currentRoad = new Road(currentRoadPoints, RoadType.S); roads.Add(currentRoad); } //Right Side for (int i = 1; i <= rightFactoryRoads; i++) { int roadX = Mathf.RoundToInt(motorwayStartX + (factorySize * i)); int distance = citySize / 2 - 2; //For the distance between the middle road and the top road, we create a straight line on x Vector3[] currentRoadPoints = new Vector3[distance]; //This should be half the size CheckSlotForRoad(roadX, citySize / 2, roadX, citySize / 2, RoadSlot.Type.S, RoadSlot.Type.S, 0); for (int j = 0; j < distance; j++) { int y = j + citySize / 2 + 1; currentRoadPoints[j] = new Vector3(roadX, 0, y); citySlots[roadX, y] = new RoadSlot(RoadSlot.Type.S, 0); //Every 4 if (j % 2 == 0 && roadX + 1 < 100) { //Adding the factory spawn citySlots[roadX + 1, y] = new FactorySlot(true, true); } } Road currentRoad = new Road(currentRoadPoints, RoadType.S); roads.Add(currentRoad); } //This does a for loop coving anything which isn't a road in the factory area for (int x = 0; x < citySize; x++) { for (int y = 0; y < (citySize / 2) - 2; y++) { if (citySlots[x, y + ((citySize / 2) + 1)] is EmptySlot) { citySlots[x, y + ((citySize / 2) + 1)] = new FactorySlot(); } } } #endregion }
private IEnumerator WaitForThread() { RoadThread roadThread = threads[threads.Count - 1]; //This will wait for that thread to be complete yield return(StartCoroutine(roadThread.WaitFor())); string cityName = Cities.GetRandomName(); GameObject parent = new GameObject(cityName); parent.tag = "City"; parent.transform.position = roadThread.position; float scaleBackX = roadThread.position.x * (cityScale - 1); float scaleBackZ = roadThread.position.z * (cityScale - 1); GeneratedSlot[,] generatedSlots = roadThread.citySlots; City lastCity = new City(cityName, roadThread.citySlots, roadThread.roads, roadThread.position); if (createDebugLines) { GameObject lineParent = new GameObject("Debug Lines"); lineParent.transform.SetParent(parent.transform); for (int i = 0; i < roadThread.roads.Count; i++) { GameObject last = Instantiate(roadDebugLine, lineParent.transform); last.name = string.Format("{0}{1} Road", roadThread.roads[i].roadType.ToString(), i); LineRenderer lineRenderer = last.GetComponent <LineRenderer>(); lineRenderer.positionCount = roadThread.roads[i].points.Length; for (int j = 0; j < lineRenderer.positionCount; j++) { //This adds the offset for each point Vector3 position = new Vector3( ((roadThread.roads[i].points[j].x + roadThread.position.x) * cityScale) - scaleBackX, ((roadThread.roads[i].points[j].y + roadThread.position.y) * cityScale), ((roadThread.roads[i].points[j].z + roadThread.position.z) * cityScale) - scaleBackZ); lineRenderer.SetPosition(j, position); } if (roadThread.roads[i].roadType == RoadType.M) { lineRenderer.startColor = Color.blue; lineRenderer.endColor = Color.blue; } else if (roadThread.roads[i].roadType == RoadType.A) { lineRenderer.startColor = Color.green; lineRenderer.endColor = Color.green; } } } if (createDebugSquares) { GameObject squareParent = new GameObject("Debug Squares"); squareParent.transform.SetParent(parent.transform); for (int x = 0; x < generatedSlots.GetLength(0); x++) { for (int y = 0; y < generatedSlots.GetLength(1); y++) { Vector3 position = new Vector3( ((x + roadThread.position.x) * cityScale) - scaleBackX, (1 + roadThread.position.y) * cityScale + 2, ((y + roadThread.position.z) * cityScale) - scaleBackZ); //Spawning a debug square GameObject square = Instantiate(roadTypeSquare, position, Quaternion.Euler(0, 0, 0), squareParent.transform); Material m = square.GetComponent <MeshRenderer>().material; if (generatedSlots[x, y] is RoadSlot) { //checking what type of road it is RoadSlot slot = (RoadSlot)generatedSlots[x, y]; if (slot.type == RoadSlot.Type.S) { m.SetColor("_BaseColor", Color.white); //if there is no connections if (!slot.hasConnection) { //GameObject sroad = Instantiate(sRoadsPrefabs[0],position, Quaternion.Euler(0,slot.primaryDirection,0), parent.transform); } } else if (slot.type == RoadSlot.Type.A) { m.SetColor("_BaseColor", Color.green); } else { m.SetColor("_BaseColor", Color.blue); } } else if (generatedSlots[x, y] is BuildingSlot) { m.SetColor("_BaseColor", Color.magenta); //Debug.Log(generatedSlots[x,y].GetType() + " X " + x + " Y " + y); } else if (generatedSlots[x, y] is FactorySlot) { if (((FactorySlot)generatedSlots[x, y]).isSpawn) { m.SetColor("_BaseColor", Color.yellow); } else { m.SetColor("_BaseColor", Color.red); } } else { m.SetColor("_BaseColor", Color.black); } } } } if (createRoads) { GameObject roadsParent = new GameObject("Roads Prefabs"); roadsParent.transform.SetParent(parent.transform); for (int x = 0; x < generatedSlots.GetLength(0); x++) { for (int y = 0; y < generatedSlots.GetLength(1); y++) { Vector3 position = new Vector3( ((x + roadThread.position.x) * cityScale) - scaleBackX, 0, ((y + roadThread.position.z) * cityScale) - scaleBackZ); if (generatedSlots[x, y] is RoadSlot) { //checking what type of road it is RoadSlot slot = (RoadSlot)generatedSlots[x, y]; if (slot.type == RoadSlot.Type.S) { //if there is no connections if (!slot.hasConnection) { GameObject sroad = Instantiate(sRoadsPrefabs[0], position, Quaternion.Euler(0, slot.primaryDirection, 0), roadsParent.transform); } else if (slot.connectedType.Count == 1) { if (slot.connectedType[0] == RoadSlot.Type.M) { } else if (slot.connectedType[0] == RoadSlot.Type.S) { GameObject sRoad = Instantiate(sRoadsPrefabs[1], position, Quaternion.Euler(0, slot.primaryDirection, 0), roadsParent.transform); } } else if (slot.connectedType.Count == 2) { //This should be the max possiable connections for a road, //but still doing an else if just in case not if (slot.connectedType[0] == RoadSlot.Type.S && slot.connectedType[1] == RoadSlot.Type.S) { GameObject sRoad = Instantiate(sRoadsPrefabs[2], position, Quaternion.Euler(0, slot.primaryDirection, 0), roadsParent.transform); } } } else if (slot.type == RoadSlot.Type.A) { if (!slot.hasConnection) { GameObject aRoad = Instantiate(aRoadsPrefabs[0], position, Quaternion.Euler(0, slot.primaryDirection, 0), roadsParent.transform); } else if (slot.connectedType.Count == 1) { position += new Vector3(0, 0.001f, 0); //This means there should only be 1 other road connecting to it if (slot.connectedType[0] == RoadSlot.Type.M) { } else { //It must be a small road as A roads don't need to connect to each other GameObject aRoad = Instantiate(aRoadsPrefabs[1], position, Quaternion.Euler(0, slot.primaryDirection, 0), roadsParent.transform); } } else if (slot.connectedType.Count == 2) { position += new Vector3(0, 0.002f, 0); if (slot.connectedType[0] == RoadSlot.Type.S && slot.connectedType[1] == RoadSlot.Type.S) { GameObject aRoad = Instantiate(aRoadsPrefabs[2], position, Quaternion.Euler(0, slot.primaryDirection, 0), roadsParent.transform); } } } else if (slot.type == RoadSlot.Type.M) { if (!slot.hasConnection) { GameObject mRoad = Instantiate(mRoadsPrefabs[0], position, Quaternion.Euler(0, slot.primaryDirection, 0), roadsParent.transform); } else if (slot.connectedType.Count == 2) { position += new Vector3(0, 0.003f, 0); GameObject mRoad = Instantiate(mRoadsPrefabs[1], position, Quaternion.Euler(0, slot.primaryDirection, 0), roadsParent.transform); } } } else if (generatedSlots[x, y] is BuildingSlot) { int index = rnd.Next(buildingPrefabs.Length); GameObject emptySlot = Instantiate(buildingPrefabs[index], position, Quaternion.Euler(0, 0, 0), roadsParent.transform); } else if (generatedSlots[x, y] is EmptySlot) { GameObject emptySlot = Instantiate(buildingPrefabs[0], position, Quaternion.Euler(0, 0, 0), roadsParent.transform); } else if (generatedSlots[x, y] is FactorySlot) { FactorySlot slot = (FactorySlot)generatedSlots[x, y]; if (slot.isSpawn) { int index = rnd.Next(factoriesPrefabs.Length); if (slot.rightSide) { GameObject factorySlot = Instantiate(factoriesPrefabs[index], position, Quaternion.Euler(0, 0, 0), roadsParent.transform); } else { //Need to move the asset over on the left side GameObject factorySlot = Instantiate(factoriesPrefabs[index], position, Quaternion.Euler(0, 0, 0), roadsParent.transform); factorySlot.transform.localPosition += Vector3.left * 46.88f; } } } loading.numberOfActionsCompleted++; } } GameObject gameObject18 = new GameObject("Minimap Lines"); gameObject18.transform.SetParent(parent.transform); gameObject18.transform.localPosition = new Vector3(0f, 100f, 0f); for (int num3 = 0; num3 < roadThread.roads.Count; num3++) { GameObject last = Instantiate(roadDebugLine, gameObject18.transform); last.layer = 15; last.name = string.Format("{0}{1} Road", roadThread.roads[num3].roadType.ToString(), num3); LineRenderer lineRenderer = last.GetComponent <LineRenderer>(); lineRenderer.positionCount = roadThread.roads[num3].points.Length; for (int num4 = 0; num4 < lineRenderer.positionCount; num4++) { Vector3 position3 = new Vector3((roadThread.roads[num3].points[num4].x + roadThread.position.x) * (float)RoadGenerator.cityScale - scaleBackX, (roadThread.roads[num3].points[num4].y + roadThread.position.y) * (float)RoadGenerator.cityScale + gameObject18.transform.position.y, (roadThread.roads[num3].points[num4].z + roadThread.position.z) * (float)RoadGenerator.cityScale - scaleBackZ); lineRenderer.SetPosition(num4, position3); } if (roadThread.roads[num3].roadType == RoadType.M) { lineRenderer.startColor = Color.blue; lineRenderer.endColor = Color.blue; } else if (roadThread.roads[num3].roadType == RoadType.A) { lineRenderer.startColor = Color.green; lineRenderer.endColor = Color.green; } } } city = lastCity; //This calls to the RoomSwitcher to spawn the rooms in as all of the roads and buildings have been spawned //roomSwitcher.SetRooms(); }