Ok, let me put it in a way I can understand it. and hopefully it will work over for you.
Imagine that we are creating a race game, and each track piece is supposed to fit together to make a race track. Now, imagine we have only 4 sections of track we want to lay down. Straight, right, left and Y. with the following rules:
The straight piece can have any of the parts
The right turn, can only accept a left turn or straight piece
The left turn, can only accept the right turn or straight piece.
The Y can only accept a straight piece.
Next we create prefabs to make the rules. 4 prefabs, each with a Script (RaceNode) that will let us assign which nodes can be placed. Remember, to create all your prefabs, then assign the prefab to the list, then save it back to the prefab.
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
public class RaceNode : MonoBehaviour
{
// spawnable positions are rotated for the next node to dock with it.
public Transform[] spawnablePositions;
// a list of nodes this node can spawn
public GameObject[] spawnableNodes;
// a list of spawned target nodes
private GameObject[] spawnedTargets;
// spawn each node for targeting
// do not do this on instantiate, it will lock your game up
public GameObject[] SpawnChildren()
{
if (spawnablePositions == null) spawnablePositions = new Transform[0];
if (spawnableNodes == null) spawnableNodes = new GameObject[spawnablePositions.Length];
if (spawnedTargets == null) spawnedTargets = new GameObject[spawnablePositions.Length];
for (var i = 0; i < spawnedTargets.Length; i++)
{
var spawnedTarget = spawnedTargets[i];
if (spawnedTarget == null)
{
var spawnablePosition = spawnablePositions[i];
if (spawnableNodes.Length > 0 && spawnablePosition != null)
{
var node = spawnableNodes[Random.Range(0, spawnableNodes.Length)];
if (node != null)
{
spawnedTarget = Instantiate(node, spawnablePosition.position, spawnablePosition.rotation);
spawnedTargets[i] = spawnedTarget;
}
}
}
}
return spawnedTargets;
}
// get the next random node
public GameObject GetNextTarget()
{
var available = this.spawnedTargets.Where(p => p != null).ToArray();
if (available.Length == 0) return null;
return available[Random.Range(0, available.Length)];
}
public static void SpawnTrack(GameObject root, int n)
{
var work = new List<GameObject>() {root};
var children = new List<GameObject>();
for (var i = 0; i < n; i++)
{
foreach (var obj in work)
{
var node = obj.GetComponent<RaceNode>();
if (node != null)
{
children.AddRange(node.SpawnChildren());
}
}
work = children.ToList();
children.Clear();
}
}
}
We add our first piece to the board. We also need a script that will start everything (not included)
Now, with this, we call, SpawnChildren() and it will return the spawned targets. With this, we use SpawnTrack(gameObject, 5) to loop through 5 iterations of track down each respective path.
Now, you need to get the target you are heading towards. GetNextTarget() With this, when you get to that target, you do 2 things… 1 spawn 5 children of that target, (thus increasing your map) and you get the next target. Now, the beauty of it, is that when you spawn 5 more targets
Pass 100 targets, and your race is done. 
Yes, there is quite a bit more to this… Track cleanup, maybe some parenting to help keep your mind straight.