public override List<Atom> Produce(CityGenerator generator) { List<Atom> production = new List<Atom>(); // Create a new map node Rule rule = generator.RuleAtCoordinates(Node.position); MapNode spawn = new MapNode(Node.position + forward * rule.CalculateRoadLength(this, generator)); spawn.ruleType = ruleType; // Fetch the spawned node's neighbours List<MapNode> neighbours = generator.GetNeighbours(spawn, generator.neighboursSearchRadius); // Check if the node is close to one of its neighbours so that they can be merged into one node bool merged = false; Vector2 spawnPosition = spawn.PositionAsVector2; foreach (MapNode neighbour in neighbours) { // Convert coords to 2D, we don't want elevation messing around with our merging algorithm Vector2 neighbourPosition = neighbour.PositionAsVector2; // Check for proximity if (Vector2.Distance(spawnPosition, neighbourPosition) <= generator.nodeMergingMaximumDistance) { // The neighbour merges spawn = neighbour; // Stop iterating merged = true; break; } } // Create a map edge between the current map node and the spawn MapEdge spawnedEdge = new MapEdge(Node, spawn); if (!merged) { // Perform the intersection of the spawned node's edge against the neighbours' edges bool intersected = Intersect(spawn, spawnedEdge, neighbours); // Raycast to check for water RaycastHit hit; if (Physics.Raycast(spawn.position + Vector3.up * 1000f, Vector3.down, out hit)) { if (hit.collider.gameObject.tag == "Water") { // Spawned over water, remove the edge from the starting node Node.edges.Remove(spawnedEdge); // Skip this node return production; } // Set the Y coordinate of the spawned node to match the height where the raycast hit spawn.position.y = hit.point.y + 0.1f; } // Add the newly created map node to the environment generator.AddMapNode(spawn); // Continue producing only if there were no intersections if (!intersected) { // Summon a branch atom Atom branch = new BranchAtom(this); branch.Node = spawn; // Add the branch atom to the list of results and we're done production.Add(branch); } } return production; }