to start off my code was made with WSAL evens Maze generator algorithm as a base.
so I've been having this issue for awhile now and I haven't been able to find a way to solve it.
I have one script that is attached to different game objects, the script is supposed to generate random mazes, find crossing points to the other generated mazes and send them that info witch is stored in a list
---
the game itself worked fine before but after I saved the project and exited out the program, the next time I open it and ran the program I am met with the "Argument Out Of Range Exception: Index was out of range" error.
I went through my code and found the error pops up when I try to add a node prefab to the lists in the "Right To Left, Left To Right, etc." methods. I don't know what is wrong with it, but when I remove and add the script back to the second maze it decides to work again.
---
this is the code I used to generate the maze
[System.Serializable]
public class PassEvent : UnityEvent { }
public class MazeGenerator : MonoBehaviour
{
[SerializeField] MazeNode nodePrefab;
[SerializeField] Vector2Int mazeSize;
[SerializeField] float nodeSize;
public PassEvent runPassEvent;
public int num = 0;
public bool isStartNode = false;
public bool mazeBorderTop = false;
public bool mazeBorderBottom = false;
public bool mazeBorderLeft = false;
public bool mazeBorderRight = false;
public bool generateUp = false;
public bool generateDown = false;
public bool generateLeft = false;
public bool generateRight = false;
public int tpX = 0;
public int tpY = 0;
public List nodes;
public List potentialStartingNode;
public List leftTransition;
public List rightTransition;
public List upTransition;
public List downTransition;
void Start()
{
Debug.Log(" run");
nodes = new List();
potentialStartingNode = new List();
leftTransition = new List();
rightTransition = new List();
upTransition = new List();
downTransition = new List();
GenerateMazePlate(mazeSize);
if (runPassEvent == null)
{
runPassEvent = new PassEvent();
}
}
// generates the nodes
void GenerateMazePlate(Vector2Int size)
{
for (int x = 0; x < size.x; x++) // creates nodes
{
for (int y = 0; y < size.y; y++)
{
Vector3 nodePos = new Vector3(x - (size.x / 2f), 0, y - (size.y / 2f)) * nodeSize;
MazeNode newNode = Instantiate(nodePrefab, nodePos, Quaternion.identity, transform);
nodes.Add(newNode);
}
}
gameObject.transform.position = new Vector3(tpX, 0, tpY);
GetOutsideWalls(mazeSize);
if (isStartNode)
{
GenerateMazeInstant(size);
}
}
// gets every node on the outside of a plate and stores it
// doesn't work on plates under 10x10
void GetOutsideWalls(Vector2Int size)
{
int sum = size.x * size.y;
int a = size.x - 1;
int b = 0;
int full = sum - 1;
int c = full - size.x + 1;
int u = 0;
int i = 0;
int x = 0;
while (i <= size.x - 1) // gets left and right side
{
leftTransition.Add(nodes[b + i]);
//leftTransition[x].SetState(NodeState.Transition);
rightTransition.Add(nodes[c + i]);
//rightTransition[x].SetState(NodeState.Transition);
i++;
x++;
}
i = 0;
x = 0;
while (i <= size.y - 1) // gets top and bottom
{
upTransition.Add(nodes[a + u]);
//upTransition[x].SetState(NodeState.Transition);
downTransition.Add(nodes[b + u]);
//downTransition[x].SetState(NodeState.Transition);
u = u + size.x;
if (u == sum)
{
u = sum - 1;
}
i++;
x++;
}
}
// recives the position of the crossing node on the other plate and marks them, removes walls
public void RightToLeft(int lNode, int num) // right to left
{
if (num == 1)
{
//Debug.Log(gameObject + " RUN");
potentialStartingNode.Add(leftTransition[lNode]);
leftTransition[lNode].SetState(NodeState.Other); // color
leftTransition[lNode].RemoveWall(1); // x wall
}
}
public void LeftToRight(int rNode, int num) // left to right
{
if (num == 2)
{
potentialStartingNode.Add(rightTransition[rNode]);
rightTransition[rNode].SetState(NodeState.Other);
rightTransition[rNode].RemoveWall(0);
}
}
public void TopToBottom(int bNode, int num) // top to bottom
{
if (num == 3)
{
potentialStartingNode.Add(downTransition[bNode]);
downTransition[bNode].SetState(NodeState.Other);
downTransition[bNode].RemoveWall(3);
}
}
public void BottomToTop(int tNode, int num) // bottom to top
{
if (num == 4)
{
potentialStartingNode.Add(upTransition[tNode]);
upTransition[tNode].SetState(NodeState.Other);
upTransition[tNode].RemoveWall(2);
}
}
public void StartNextPlate(int no, int num)
{
if (num == 5)
{
no = 0;
GenerateMazeInstant(mazeSize);
}
}
// generates the maze
void GenerateMazeInstant(Vector2Int size)
{
if (isStartNode)
{
List currentPath = new List();
List completedNodes = new List();
currentPath.Add(nodes[180]); // chooses the starting node
currentPath[0].SetState(NodeState.Current);
while (completedNodes.Count < nodes.Count) // checks nodes
{
// check node next too current node
List possibleNextNodes = new List();
List possibleDirections = new List();
int currentNodeIndex = nodes.IndexOf(currentPath[currentPath.Count - 1]);
int currentNodex = currentNodeIndex / size.y;
int currentNodeY = currentNodeIndex % size.y;
if (currentNodex < size.x - 1)
{
// Check node to the right of the current node
if (!completedNodes.Contains(nodes[currentNodeIndex + size.y]) && !currentPath.Contains(nodes[currentNodeIndex + size.y]))
{
possibleDirections.Add(1);
possibleNextNodes.Add(currentNodeIndex + size.y);
}
}
if (currentNodex > 0)
{
// Check node to the left of the current node
if (!completedNodes.Contains(nodes[currentNodeIndex - size.y]) && !currentPath.Contains(nodes[currentNodeIndex - size.y]))
{
possibleDirections.Add(2);
possibleNextNodes.Add(currentNodeIndex - size.y);
}
}
if (currentNodeY < size.y - 1)
{
// check node above the current node
if (!completedNodes.Contains(nodes[currentNodeIndex + 1]) && !currentPath.Contains(nodes[currentNodeIndex + 1]))
{
possibleDirections.Add(3);
possibleNextNodes.Add(currentNodeIndex + 1);
}
}
if (currentNodeY > 0)
{
//Check node below the current node
if (!completedNodes.Contains(nodes[currentNodeIndex - 1]) && !currentPath.Contains(nodes[currentNodeIndex - 1]))
{
possibleDirections.Add(4);
possibleNextNodes.Add(currentNodeIndex - 1);
}
}
//Choose next node
if (possibleDirections.Count > 0)
{
int chosenDirection = Random.Range(0, possibleDirections.Count);
MazeNode chosenNode = nodes[possibleNextNodes[chosenDirection]];
switch (possibleDirections[chosenDirection])
{
case 1:
chosenNode.RemoveWall(1);
currentPath[currentPath.Count - 1].RemoveWall(0);
break;
case 2:
chosenNode.RemoveWall(0);
currentPath[currentPath.Count - 1].RemoveWall(1);
break;
case 3:
chosenNode.RemoveWall(3);
currentPath[currentPath.Count - 1].RemoveWall(2);
break;
case 4:
chosenNode.RemoveWall(2);
currentPath[currentPath.Count - 1].RemoveWall(3);
break;
}
currentPath.Add(chosenNode);
}
else
{
completedNodes.Add(currentPath[currentPath.Count - 1]);
currentPath.RemoveAt(currentPath.Count - 1);
}
}
GenerateNodesUp();
Debug.Log(gameObject + " Complete 1");
}
if (!isStartNode) // is not the starting plate
{
List currentPath = new List();
List completedNodes = new List();
currentPath.Add(potentialStartingNode[Random.Range(0, potentialStartingNode.Count)]); // chooses the starting node
currentPath[0].SetState(NodeState.Current);
while (completedNodes.Count < nodes.Count) // checks nodes
{
// check node next too current node
List possibleNextNodes = new List();
List possibleDirections = new List();
int currentNodeIndex = nodes.IndexOf(currentPath[currentPath.Count - 1]);
int currentNodex = currentNodeIndex / size.y;
int currentNodeY = currentNodeIndex % size.y;
if (currentNodex < size.x - 1)
{
// Check node to the right of the current node
if (!completedNodes.Contains(nodes[currentNodeIndex + size.y]) && !currentPath.Contains(nodes[currentNodeIndex + size.y]))
{
possibleDirections.Add(1);
possibleNextNodes.Add(currentNodeIndex + size.y);
}
}
if (currentNodex > 0)
{
// Check node to the left of the current node
if (!completedNodes.Contains(nodes[currentNodeIndex - size.y]) && !currentPath.Contains(nodes[currentNodeIndex - size.y]))
{
possibleDirections.Add(2);
possibleNextNodes.Add(currentNodeIndex - size.y);
}
}
if (currentNodeY < size.y - 1)
{
// check node above the current node
if (!completedNodes.Contains(nodes[currentNodeIndex + 1]) && !currentPath.Contains(nodes[currentNodeIndex + 1]))
{
possibleDirections.Add(3);
possibleNextNodes.Add(currentNodeIndex + 1);
}
}
if (currentNodeY > 0)
{
//Check node below the current node
if (!completedNodes.Contains(nodes[currentNodeIndex - 1]) && !currentPath.Contains(nodes[currentNodeIndex - 1]))
{
possibleDirections.Add(4);
possibleNextNodes.Add(currentNodeIndex - 1);
}
}
//Choose next node
if (possibleDirections.Count > 0)
{
int chosenDirection = Random.Range(0, possibleDirections.Count);
MazeNode chosenNode = nodes[possibleNextNodes[chosenDirection]];
switch (possibleDirections[chosenDirection])
{
case 1:
chosenNode.RemoveWall(1);
currentPath[currentPath.Count - 1].RemoveWall(0);
break;
case 2:
chosenNode.RemoveWall(0);
currentPath[currentPath.Count - 1].RemoveWall(1);
break;
case 3:
chosenNode.RemoveWall(3);
currentPath[currentPath.Count - 1].RemoveWall(2);
break;
case 4:
chosenNode.RemoveWall(2);
currentPath[currentPath.Count - 1].RemoveWall(3);
break;
}
currentPath.Add(chosenNode);
}
else
{
completedNodes.Add(currentPath[currentPath.Count - 1]);
currentPath.RemoveAt(currentPath.Count - 1);
}
}
if (generateUp)
{
GenerateNodesUp();
}
if (generateLeft)
{
GenerateNodesLeft();
}
if (generateRight)
{
GenerateNodesRight();
}
Debug.Log( gameObject + " Complete 2");
}
}
// randomly generate which nodes are crossing nodes
void GenerateNodesUp()
{
int tPath = Random.Range(1, 4);
int lPath = Random.Range(1, 4);
int rPath = Random.Range(1, 4);
//Debug.Log(" top " + tPath);
//Debug.Log(" left " + lPath);
//Debug.Log(" right " + rPath);
// randomly selects a node in the list to become a crossing node, crossing node amount is determined by rng
// could instantly put crossing nodes into a list
int x = 1;
if (!mazeBorderTop)
{
while (x <= tPath)
{
MazeNode currentRandom = upTransition[Random.Range(0, upTransition.Count)];
if (currentRandom.walls[2].activeSelf)
{
currentRandom.SetState(NodeState.Current);
currentRandom.RemoveWall(2);
x++;
}
}
}
if (!mazeBorderLeft)
{
x = 1;
while (x <= lPath)
{
MazeNode currentRandom = leftTransition[Random.Range(0, leftTransition.Count)];
if (currentRandom.walls[1].activeSelf)
{
currentRandom.SetState(NodeState.Current);
currentRandom.RemoveWall(1);
x++;
}
}
}
if (!mazeBorderRight)
{
x = 1;
while (x <= rPath)
{
MazeNode currentRandom = rightTransition[Random.Range(0, rightTransition.Count)];
if (currentRandom.walls[0].activeSelf)
{
currentRandom.SetState(NodeState.Current);
currentRandom.RemoveWall(0);
x++;
}
}
}
FindCrossingUp(rPath, lPath, tPath);
}
void GenerateNodesLeft()
{
int tPath = Random.Range(1, 4);
int lPath = Random.Range(1, 4);
int x = 1;
if (!mazeBorderTop)
{
while (x <= tPath)
{
MazeNode currentRandom = upTransition[Random.Range(0, upTransition.Count)];
if (currentRandom.walls[2].activeSelf)
{
currentRandom.SetState(NodeState.Current);
currentRandom.RemoveWall(2);
x++;
}
}
}
if (!mazeBorderLeft)
{
x = 1;
while (x <= lPath)
{
MazeNode currentRandom = leftTransition[Random.Range(0, leftTransition.Count)];
if (currentRandom.walls[1].activeSelf)
{
currentRandom.SetState(NodeState.Current);
currentRandom.RemoveWall(1);
x++;
}
}
}
FindCrossingLeft(tPath, lPath);
}
void GenerateNodesRight()
{
int tPath = Random.Range(1, 4);
int rPath = Random.Range(1, 4);
int x = 1;
if (!mazeBorderTop)
{
while (x <= tPath)
{
MazeNode currentRandom = upTransition[Random.Range(0, upTransition.Count)];
if (currentRandom.walls[2].activeSelf)
{
currentRandom.SetState(NodeState.Current);
currentRandom.RemoveWall(2);
x++;
}
}
}
if (!mazeBorderRight)
{
x = 1;
while (x <= rPath)
{
MazeNode currentRandom = rightTransition[Random.Range(0, rightTransition.Count)];
if (currentRandom.walls[0].activeSelf)
{
currentRandom.SetState(NodeState.Current);
currentRandom.RemoveWall(0);
x++;
}
}
}
FindCrossingRight(tPath, rPath);
}
//finds the position of the crossing nodes
void FindCrossingUp(int rPath, int lPath, int tPath)
{
List crossRight = new List();
List crossLeft = new List();
List crossTop = new List();
// gets the node position of each crossing section
int x = 0;
int y = 0;
while (x < rightTransition.Count)
{
if (!rightTransition[x].walls[0].activeSelf)
{
if (y <= rPath)
{
crossRight.Add(x);
y++;
}
}
x++;
}
x = 0;
y = 0;
while (x < leftTransition.Count)
{
if (!leftTransition[x].walls[1].activeSelf)
{
if (y <= lPath)
{
crossLeft.Add(x);
y++;
}
}
x++;
}
x = 0;
y = 0;
while (x < upTransition.Count)
{
if (!upTransition[x].walls[2].activeSelf)
{
if (y <= tPath)
{
crossTop.Add(x);
y++;
}
}
x++;
}
// sends the node position for the crossing sections
y = 0;
num = 1;
while (y < rPath)
{
runPassEvent.Invoke(crossRight[y], num);
y++;
}
y = 0;
num = 2;
while (y < lPath)
{
runPassEvent.Invoke(crossLeft[y], num);
y++;
}
y = 0;
num = 3;
while (y < tPath)
{
runPassEvent.Invoke(crossTop[y], num);
y++;
}
num = 5;
runPassEvent.Invoke(y, num);
}
void FindCrossingLeft(int tPath, int lPath)
{
List crossLeft = new List();
List crossTop = new List();
// gets the node position of each crossing section
int x = 0;
int y = 0;
while (x < leftTransition.Count)
{
if (!leftTransition[x].walls[1].activeSelf)
{
if (y <= lPath)
{
crossLeft.Add(x);
y++;
}
}
x++;
}
x = 0;
y = 0;
while (x < upTransition.Count)
{
if (!upTransition[x].walls[2].activeSelf)
{
if (y <= tPath)
{
crossTop.Add(x);
y++;
}
}
x++;
}
// sends the node position for the crossing sections
y = 0;
num = 2;
while (y < lPath)
{
runPassEvent.Invoke(crossLeft[y], num);
y++;
}
y = 0;
num = 3;
while (y < tPath)
{
runPassEvent.Invoke(crossTop[y], num);
y++;
}
num = 5;
runPassEvent.Invoke(y, num);
}
void FindCrossingRight(int tPath, int rPath)
{
List crossRight = new List();
List crossTop = new List();
// gets the node position of each crossing section
int x = 0;
int y = 0;
while (x < rightTransition.Count)
{
if (!rightTransition[x].walls[0].activeSelf)
{
if (y <= rPath)
{
crossRight.Add(x);
y++;
}
}
x++;
}
x = 0;
y = 0;
while (x < upTransition.Count)
{
if (!upTransition[x].walls[2].activeSelf)
{
if (y <= tPath)
{
crossTop.Add(x);
y++;
}
}
x++;
}
// sends the node position for the crossing sections
y = 0;
num = 1;
while (y < rPath)
{
runPassEvent.Invoke(crossRight[y], num);
y++;
}
y = 0;
num = 3;
while (y < tPath)
{
runPassEvent.Invoke(crossTop[y], num);
y++;
}
num = 5;
runPassEvent.Invoke(y, num);
}
}
---
and this is the code I used for the node Prefabs
public enum NodeState
{
Available,
Current,
Completed,
Transition,
Other
}
public class MazeNode : MonoBehaviour
{
public GameObject[] walls;
[SerializeField] MeshRenderer floor; // used to check the state of the node, dont really need
public void RemoveWall(int wallToRemove)
{
walls[wallToRemove].gameObject.SetActive(false);
}
public void SetState(NodeState state) // use to show state of node
{
switch (state)
{
case NodeState.Available:
floor.material.color = Color.white;
break;
case NodeState.Current:
floor.material.color = Color.yellow;
break;
case NodeState.Completed:
floor.material.color = Color.blue;
break;
case NodeState.Transition:
floor.material.color = Color.green;
break;
case NodeState.Other:
floor.material.color = Color.red;
break;
}
}
}
---
I know its a lot and kind of complicated but any help will do
↧