The x and y dimensions need to be the same or there will be strange results and an array out of bounds exception. Gonna investigate more and see if I find the root cause.
Do you mean with the maze size? It's working fine on my end. You can check the GitHub to see if you typed something wrong or if I messed something up in the video. Let me know what happened when you find it
For 2D games, using this implementation, would you recommend us making a separate wall sprite and spawning that for the walls? My game is designed in pixel art so I am curious how its best to design the art for this solution.
Sorry for the late reply. A tilemap would be more efficient, but spawning the objects is easier to program and probably better if the walls aren't the same size as a tile. The thing to keep in mind with the art is that with the solution in the video, the corners overlap which may be unpredictable when combined with textures. You could simply add corner objects and reduce the size of the walls to fix that.
I meant to cover that in the tutorial but I forgot to lol. All you have to do is make the node object the size you want, then in the script, add a variable for nodeSize and where you calculate nodePos, multiply that by nodeSize. Vector3 nodePos = new Vector3(x - (size.x / 2f), 0, y - (size.y / 2f)) * nodeSize; I just added it to the github page so you can find the changes there as well.
Great video and tutorial! I have a question that may sound ridiculous (I'm really bad at programming), is there a way to get rid of the randomization and just have it generate a single maze level?
Thanks! If you apply a seed to Random before generating the maze, it should be the same every time. You can do that with this line: Random.seed = [seed];
@@wsalevan Wow I didn't expect the fast response hahahahaha so for example, taking this line of code: currentPath.Add(nodes[Random.Range(0, nodes.Count)]); I'd change it to currentPath.Add(nodes[Random.seed = [seed]]); ?
The line I mentioned should go before the maze starts generating. Everything else should stay the same. Also, replace [seed] with an integer value. Let me know if you have any issues with it!
Just finished my AI semi-tasks, where i used all kind of searches through graphs, i had a LITLE BIT of a ptsd when i hard depth first search at 0:08, but THIS is a good example how and why should i use this algorith in real tasks, instead of go through a graphs.txt wich is fcking 2000lines long with graphs :D
Amazing tutorial! However, I have an issue. When I play the game it says: ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection. Parameter name: index This is in reference of the line where it has to choose the next node: MazeNode chosenNode = nodes[possibleNextNodes[chosenDirection]]; (line 94) I don't know what does that mean but I checked the code and I have the same as you and I don't have any textures on my walls or anything similar. In the game all the mazes appear whit the walls and it does something weird because only sometimes the yellow trail goes for a couple blocks but then stops. If you could help if would be perfect ❤. Thanks in advance and sorry for my bad English.
Thanks! Are your mazes rectangles? If so, you may have mistyped some x and y variables in your code. See if you still get errors when using a square maze
@@wsalevan Thanks for answering so fast! I checked all the code several times and I as far as I could tell everything was correct and my mazes also had the same dimensions as yours. However, I tried it on a new project and it worked. I don't know why it wasn't working on the first place but now it is which is enough for me. One question: Can I use textures on the floor and the walls? Like putting them on the prefab so the maze is generated with those textures. In any case thanks for the tutorial, you saved my life ❤.
i was wondering how to use textures on them without overlapping, for some reason i couldnt choose the right dimensions to avoid it. other than that great job
I didn't think about textures when making the video since I was just using a solid texture so that's my bad lol. They overlap a little bit so that there's no gap, but you can just change the 1.1 scales down to 1.0 and then add corner objects to it
You can create a first node variable and set it when setting the start position in the algorithm. Then you can continuously set an end node variable when adding a node to the current path list. However, if you're trying to create like a player and a goal, you're better off setting them to random node positions because you can control it better that way.
Hey, I'm trying to make it so the player starts outside the maze and then after finishing he can just leave (not catching a portal) by just walking outside. Is there a way to make it so the entrance to the maze is always at the bottom center and the exit at the top but random? I was thinking that if I have a way to know how to make the maze start generating in the bottom center (entrance) maybe I would be good to go
Because every point is reachable by any other point in the maze, you can just delete one of the nodes from the bottom and one from the top when the maze is generated without any issues.
Thanks! You should be able to just delete all the node objects and then run the GenerateMaze method again to reset it. Let me know if you have any trouble!
This algorithm depends on knowing the size of the maze, so while you can split the maze into chunks and only have those chunks generate when in range of the player, you can't make an infinite maze using this algorithm. You can modify it to allow the walls at the edge of the chunk to be disabled, and then when a new chunk is generated, it can detect which walls from the first one are disabled and generate the chunk based on that. I might look into that.
You can create a first node variable that gets set when choosing the starting node in the algorithm. Then you can create a last node variable that gets set every time you add a node to the current path. However, you're gonna get better results by choosing random nodes from the nodes array
Amazing tutorial dude, just a question, how can I spawn a player and a treasure at the end left corner and in the superior right corner respectively? Thanks!
For anyone wondering how to spawn the last (superior corner to the right) and/or initial position of the maze (corner left down) check these 2 methos I added after the maze was generated: private void InitializePlayer() { Instantiate(_player, _nodes[0].transform.position, Quaternion.identity); } private void InitializeTreasure() { int lastIndex = _nodes.Count - 1; Instantiate(_treasure, _nodes[lastIndex].transform.position, Quaternion.identity); } being _treasure and _player the prefabs to instantiate.
Great tutorial!! very clear and educational! i just have one question/issue. How do i stop the generator from remove my most outerwalls (as in the edges of the maze if you know what i mean)
In lines 49, 59, 69 and 79 (the 4 if-statements), make sure you've typed currentNodeX in the first two and currentNodeY in the second two. I was facing the same issue, and discovered that a typo was the culprit. Hope this helps!
When i try and remove my walls i get an error. “IndexOutOfRangeException:” and it brings me to the MazeNode “walls[wallToRemove] ect. Of code. Is there some ways to fix this?
Thank you for the speedy response. I just created a new project and copied and pasted everything, works now. The only thing that im having trouble with now is my outside walls are being removed. Any work around the this issue?
Hmmm they shouldn't be getting removed with the code in the video. Check the if statements that check for the possible directions. It shouldn't be able to move in a direction that will lead it off the edge. If you're having trouble, send me the code and I'll look over it
So just found two other errors which I can't solve. Toward the end when I add in the else statement that turns the tile blue (without removing the wall) the maze generates normally and when it gets to the first blue tile, it freezes and doesn't progress to the next. I think that is part leading to the second issue in that when I add in the switch statements with the 4 cases the it ONLY fills in one yellow tile then nothing more. Hopefully you see this
Okay slowly making the progress, figured out the first bug but still have issues with the last one. With all the code written (excluding the bit of code that makes it run instantly), when I run it, it chooses the starting node, highlights it yellow then stops. Only one node. Will continue trying to solve it but might need help :)
So I think I boiled it down, the code in the mazenode file, with the remove wall code, doesn't actually remove the walls, my best guess. Would love any guidance
Sorry I responded late. Are you able to send me your code? I can't really tell what exactly is causing the problem with your description. Are you getting an error when trying to remove walls? Because if you're not, it shouldn't stop the algorithm from continuing.
First off, love this tutorial, trying to get it to work however getting an error for the script that visualize the floor. for the NodeState.Available etc they're all giving me Cannot implicitly convert type 'NodeState' to 'int'. An explicit conversion exists (are you missing a cast?) The solution it gives me is to put a Int Infront of the NodeState. That's the first, the second, when I go back to Unity there is no "Floor" option for me to drag the script into even though Floor should be public. help? Sorry reposting this, this is my actual youtube account lol
Yup! All you gotta do is move the camera above the maze and switch it to orthographic mode. Or, if you want it to be on the x and y axis like normal 2d, you can change z to y in the code and rotate the maze modes. If you have any trouble with that, let me know
@@wsalevan thank you very much for answering and thank you for solving my question, but I have another question, is there any way to do this algorithm in a unity 2d project instead of 3d? since I have planned to make a pixel art style 2d game
What I described above will work in 2d. You can just replace the y axis in the code with the z axis and then switch out the wall objects with 2d objects. If you want, I can create a 2d version of the GitHub so you can see what I mean
Sorry for the late reply! You should be able to make a standard player script and just throw it into the scene. You could either instantiate it in the MazeGenerator script after the maze is done generating or just disable it in the scene and then have the MazeGenerator script enable it. I will be making a new tutorial about this relatively soon and I'll be sure to include this in it.
Thats a really nice tutorial, it works very well. But does anyone know how to make improve the performance of the game? like occlusion culling and that type of thing, cuz right now everything is being rendered at once
Thanks! I think occlusion culling is enabled by default, but since it's generated at runtime, only dynamic occlusion works, which I don't think helps much. One way to improve performance is to split the maze into chunks and only enable chunks that are within the player's view distance.
I did make a very very basic dynamic occlusion system, it help a bit. But I didn't implemented this chunk idea, ill look more into it and see how I can add it.
@@wsalevan I later found a way to save the maze as a prefab during runtime using PrefabUtility.SaveAsPrefabAsset in the Unity Editor functionality. Thank you so much for this tutorial. It's very helpful.🙂
@@wsalevanI later found a way to make it permanent by saving it as a prefab during runtime and then dragging the prefab into my work as a scene object. I used PrefabUtility.SaveAsPrefabAsset, a Unity Editor functionality. Thank you so much for this tutorial. It was very helpful.
Any chance you'd be willing to do a session in helping me generate this in an isometric view. I've been trying to transfer the code but I'm new to unity and pretty sure setting up the mazenodes is what's getting me
Inside of the code where you set the position of the nodes, instead of setting the z position, set the y position. Then make the node walls out of 2D objects and use the Y axis instead of the Z axis.
@@wsalevan thank you so much for agreeing to help me out! below is the link to the google drive. please let me know if there is anything else you need. drive.google.com/file/d/1BWFew4-Iws0A9ljDfENdYqdJZoGOv92x/view?usp=sharing
good tutorial, but i dont see why it wouldnt work if you go N E S W instead of E W N S ? seeing you are using ints, instead of saying 1 2 3 4 you would say 3 1 4 2, figure of speech. have a good one and keep it up, also with the laughter
Thanks! Yeah you certainly can do N E S W instead. The reason I said it has to be E W N S is so the walls were in the right order for what I did in the code. You can change the order of the walls as long as you change it in both the code and the inspector. I did it E W N S because I like to keep both x's together and both y's together.
@@wsalevan Yeah, it was just a comment, to that you said at the start, that you have to do it that way, or it wont work. I kinda modified your script a bit, using co ordinates, checking if the Completed list has the item or the current list has the item. Basically used Vector3(thispos.x -1, thispos.y, thispos.z) for checking if there is a node listed west of our active node
Super helpful and informative, and between you and me: easily the cleanest maze generator script on youtube.
Thanks! I'm glad I could help
Great tutorial. Simple, yet very effective. You have no idea how long i was searching for this kind of a tutorial, and i couldn't find any.
This works really well. Fantastic job.
Thanks!
Thank you so much for letting me know easily. I wish you happiness.
I'm glad I could help!
Thank you so much! It's exactly what I searched!
Glad I could help!
amazing video
absolutely loved it
very helpful. thank you for making this tutorial. 👍
absolute legend u actually saved me
I'm glad I could help!
The x and y dimensions need to be the same or there will be strange results and an array out of bounds exception. Gonna investigate more and see if I find the root cause.
Do you mean with the maze size? It's working fine on my end. You can check the GitHub to see if you typed something wrong or if I messed something up in the video. Let me know what happened when you find it
@@wsalevan It was my bad, I set
int currentNodeY = currentNodeIndex % size.x;
but it should have been size.y;
Gotcha. That's a very easy mistake to make and I've definitely done that many times before lol. Thanks for letting me know!
For 2D games, using this implementation, would you recommend us making a separate wall sprite and spawning that for the walls? My game is designed in pixel art so I am curious how its best to design the art for this solution.
Sorry for the late reply. A tilemap would be more efficient, but spawning the objects is easier to program and probably better if the walls aren't the same size as a tile. The thing to keep in mind with the art is that with the solution in the video, the corners overlap which may be unpredictable when combined with textures. You could simply add corner objects and reduce the size of the walls to fix that.
You should make an tutorial on how to acttually make a game with this turorial and btw it is the best tutorial on maze generator
Great tutorial but how do I scale the size of the maze node so my player can fit in the maze without the nodes spawning in to each other
I meant to cover that in the tutorial but I forgot to lol. All you have to do is make the node object the size you want, then in the script, add a variable for nodeSize and where you calculate nodePos, multiply that by nodeSize.
Vector3 nodePos = new Vector3(x - (size.x / 2f), 0, y - (size.y / 2f)) * nodeSize;
I just added it to the github page so you can find the changes there as well.
@@wsalevan Hey thanks for the script can I use it for commercial use. I will put you in the credits.
Yes you can use it however you want
tysm, its really useful
You're welcome! I'm glad it helped!
Great . 👍
Thanks!
Great video and tutorial! I have a question that may sound ridiculous (I'm really bad at programming), is there a way to get rid of the randomization and just have it generate a single maze level?
Thanks! If you apply a seed to Random before generating the maze, it should be the same every time.
You can do that with this line: Random.seed = [seed];
@@wsalevan Wow I didn't expect the fast response hahahahaha
so for example, taking this line of code: currentPath.Add(nodes[Random.Range(0, nodes.Count)]);
I'd change it to currentPath.Add(nodes[Random.seed = [seed]]); ?
The line I mentioned should go before the maze starts generating. Everything else should stay the same. Also, replace [seed] with an integer value. Let me know if you have any issues with it!
Just finished my AI semi-tasks, where i used all kind of searches through graphs, i had a LITLE BIT of a ptsd when i hard depth first search at 0:08, but THIS is a good example how and why should i use this algorith in real tasks, instead of go through a graphs.txt wich is fcking 2000lines long with graphs :D
Amazing tutorial! However, I have an issue. When I play the game it says: ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index
This is in reference of the line where it has to choose the next node: MazeNode chosenNode = nodes[possibleNextNodes[chosenDirection]]; (line 94)
I don't know what does that mean but I checked the code and I have the same as you and I don't have any textures on my walls or anything similar. In the game all the mazes appear whit the walls and it does something weird because only sometimes the yellow trail goes for a couple blocks but then stops. If you could help if would be perfect ❤.
Thanks in advance and sorry for my bad English.
Thanks! Are your mazes rectangles? If so, you may have mistyped some x and y variables in your code. See if you still get errors when using a square maze
@@wsalevan Thanks for answering so fast! I checked all the code several times and I as far as I could tell everything was correct and my mazes also had the same dimensions as yours. However, I tried it on a new project and it worked. I don't know why it wasn't working on the first place but now it is which is enough for me.
One question: Can I use textures on the floor and the walls? Like putting them on the prefab so the maze is generated with those textures.
In any case thanks for the tutorial, you saved my life ❤.
I'm glad you managed to get it working! You can add textures and whatever else you want to the floor and walls
i was wondering how to use textures on them without overlapping, for some reason i couldnt choose the right dimensions to avoid it. other than that great job
I didn't think about textures when making the video since I was just using a solid texture so that's my bad lol. They overlap a little bit so that there's no gap, but you can just change the 1.1 scales down to 1.0 and then add corner objects to it
how to store the first node position in a vector??
edit: also the last node position
You can create a first node variable and set it when setting the start position in the algorithm. Then you can continuously set an end node variable when adding a node to the current path list. However, if you're trying to create like a player and a goal, you're better off setting them to random node positions because you can control it better that way.
Hey, I'm trying to make it so the player starts outside the maze and then after finishing he can just leave (not catching a portal) by just walking outside. Is there a way to make it so the entrance to the maze is always at the bottom center and the exit at the top but random? I was thinking that if I have a way to know how to make the maze start generating in the bottom center (entrance) maybe I would be good to go
Because every point is reachable by any other point in the maze, you can just delete one of the nodes from the bottom and one from the top when the maze is generated without any issues.
Amazing video! This helped me a bunch but I was wondering if there is a way to add a Reset feature? I'm using it for a class module
Thanks! You should be able to just delete all the node objects and then run the GenerateMaze method again to reset it. Let me know if you have any trouble!
Is there a way to increase the scale of the maze without breaking everything so that a navmesh can be used?
How to .SetActive(false) for the Main Camera after the Maze is completed? Sorry, I'm a beginner and don't know how to speak English.
Also, does anyone know how to make this a procedural script? Like creating new areas at play instead of at once to make it infinite.
This algorithm depends on knowing the size of the maze, so while you can split the maze into chunks and only have those chunks generate when in range of the player, you can't make an infinite maze using this algorithm. You can modify it to allow the walls at the edge of the chunk to be disabled, and then when a new chunk is generated, it can detect which walls from the first one are disabled and generate the chunk based on that. I might look into that.
How can we add a ball in the first node and an ending point in the last node?
You can create a first node variable that gets set when choosing the starting node in the algorithm. Then you can create a last node variable that gets set every time you add a node to the current path. However, you're gonna get better results by choosing random nodes from the nodes array
@@wsalevan ok thanks
Amazing tutorial dude, just a question, how can I spawn a player and a treasure at the end left corner and in the superior right corner respectively? Thanks!
For anyone wondering how to spawn the last (superior corner to the right) and/or initial position of the maze (corner left down) check these 2 methos I added after the maze was generated:
private void InitializePlayer()
{
Instantiate(_player, _nodes[0].transform.position, Quaternion.identity);
}
private void InitializeTreasure()
{
int lastIndex = _nodes.Count - 1;
Instantiate(_treasure, _nodes[lastIndex].transform.position, Quaternion.identity);
}
being _treasure and _player the prefabs to instantiate.
Thanks! Good job figuring out your own question. Sorry I was late to respond
@@wsalevan All good. wanted to help!
Great tutorial!! very clear and educational! i just have one question/issue. How do i stop the generator from remove my most outerwalls (as in the edges of the maze if you know what i mean)
In lines 49, 59, 69 and 79 (the 4 if-statements), make sure you've typed currentNodeX in the first two and currentNodeY in the second two. I was facing the same issue, and discovered that a typo was the culprit. Hope this helps!
When i try and remove my walls i get an error. “IndexOutOfRangeException:” and it brings me to the MazeNode “walls[wallToRemove] ect. Of code. Is there some ways to fix this?
Do you have your wall variables set in your maze node prefab?
Thank you for the speedy response. I just created a new project and copied and pasted everything, works now. The only thing that im having trouble with now is my outside walls are being removed. Any work around the this issue?
Hmmm they shouldn't be getting removed with the code in the video. Check the if statements that check for the possible directions. It shouldn't be able to move in a direction that will lead it off the edge. If you're having trouble, send me the code and I'll look over it
Again, thank you for the fast response. I will play around with the code and figure it out. Im sure its just a simple fix! Great video very helpful!
So just found two other errors which I can't solve. Toward the end when I add in the else statement that turns the tile blue (without removing the wall) the maze generates normally and when it gets to the first blue tile, it freezes and doesn't progress to the next. I think that is part leading to the second issue in that when I add in the switch statements with the 4 cases the it ONLY fills in one yellow tile then nothing more. Hopefully you see this
Okay slowly making the progress, figured out the first bug but still have issues with the last one. With all the code written (excluding the bit of code that makes it run instantly), when I run it, it chooses the starting node, highlights it yellow then stops. Only one node. Will continue trying to solve it but might need help :)
So I think I boiled it down, the code in the mazenode file, with the remove wall code, doesn't actually remove the walls, my best guess. Would love any guidance
Sorry I responded late. Are you able to send me your code? I can't really tell what exactly is causing the problem with your description. Are you getting an error when trying to remove walls? Because if you're not, it shouldn't stop the algorithm from continuing.
I have no idea why but youtube is not letting me comment post for some reason. I have the code on stackoverflow
When I copy your code directly from your github repo, it gives me a the referenced script on this behaviour (Game Object mazegenerator) is missing.
First off, love this tutorial, trying to get it to work however getting an error for the script that visualize the floor. for the NodeState.Available etc they're all giving me Cannot implicitly convert type 'NodeState' to 'int'. An explicit conversion exists (are you missing a cast?) The solution it gives me is to put a Int Infront of the NodeState. That's the first, the second, when I go back to Unity there is no "Floor" option for me to drag the script into even though Floor should be public. help? Sorry reposting this, this is my actual youtube account lol
NVM figured it out lol
what does node size do ??
Is there any way to make It in a top down perspective?
Yup! All you gotta do is move the camera above the maze and switch it to orthographic mode. Or, if you want it to be on the x and y axis like normal 2d, you can change z to y in the code and rotate the maze modes. If you have any trouble with that, let me know
@@wsalevan thank you very much for answering and thank you for solving my question, but I have another question, is there any way to do this algorithm in a unity 2d project instead of 3d? since I have planned to make a pixel art style 2d game
What I described above will work in 2d. You can just replace the y axis in the code with the z axis and then switch out the wall objects with 2d objects. If you want, I can create a 2d version of the GitHub so you can see what I mean
@@wsalevan could you please create the 2d version on github? many thanks
Can u make a theta (circular) maze generator ? plz
Circles scare me lol. Though I'll try to do that because different maze shapes sounds like it could be quite cool to implement
I've got a question. How I can add the player to this maze?
Sorry for the late reply! You should be able to make a standard player script and just throw it into the scene. You could either instantiate it in the MazeGenerator script after the maze is done generating or just disable it in the scene and then have the MazeGenerator script enable it.
I will be making a new tutorial about this relatively soon and I'll be sure to include this in it.
Thanks
@@wsalevan
that amazing, I did too, but I'm having difficulty when I change the size of the cube, any tips?
If you change the size of the cube, you also have to change the distance between them in the code
@wsalevan how would you go about doing that? I've been changing values in the code and cant seem to figure out what to change
In the part of the code where you set the position of the cubes, multiply the position by the size of the cube
Thats a really nice tutorial, it works very well. But does anyone know how to make improve the performance of the game? like occlusion culling and that type of thing, cuz right now everything is being rendered at once
Thanks! I think occlusion culling is enabled by default, but since it's generated at runtime, only dynamic occlusion works, which I don't think helps much. One way to improve performance is to split the maze into chunks and only enable chunks that are within the player's view distance.
I did make a very very basic dynamic occlusion system, it help a bit. But I didn't implemented this chunk idea, ill look more into it and see how I can add it.
Please how can I make the generated maze permanent and not vanishing anything I press the play button.
You can probably make an editor script that will generate it outside of runtime. I haven't tested it though
@@wsalevan I later found a way to save the maze as a prefab during runtime using PrefabUtility.SaveAsPrefabAsset in the Unity Editor functionality. Thank you so much for this tutorial. It's very helpful.🙂
@@wsalevanI later found a way to make it permanent by saving it as a prefab during runtime and then dragging the prefab into my work as a scene object. I used PrefabUtility.SaveAsPrefabAsset, a Unity Editor functionality. Thank you so much for this tutorial. It was very helpful.
Awesome! I'm glad you figured it out
Any chance you'd be willing to do a session in helping me generate this in an isometric view. I've been trying to transfer the code but I'm new to unity and pretty sure setting up the mazenodes is what's getting me
How would you be able to implement this in 2D?
Inside of the code where you set the position of the nodes, instead of setting the z position, set the y position. Then make the node walls out of 2D objects and use the Y axis instead of the Z axis.
@@wsalevan I used 2D squares to make the walls and they all look very flat. Is there any chance I can email you a screenshot of this?
@@kausarlolz you can post the screenshot to imgur or Google drive or something and send a link
@@wsalevan thank you so much for agreeing to help me out! below is the link to the google drive. please let me know if there is anything else you need. drive.google.com/file/d/1BWFew4-Iws0A9ljDfENdYqdJZoGOv92x/view?usp=sharing
Yup! Can you provide the other script as well as a screenshot of what you mean by flat?
Thanks I can made my backrooms:D
good tutorial, but i dont see why it wouldnt work if you go N E S W instead of E W N S ? seeing you are using ints, instead of saying 1 2 3 4 you would say 3 1 4 2, figure of speech. have a good one and keep it up, also with the laughter
Thanks! Yeah you certainly can do N E S W instead. The reason I said it has to be E W N S is so the walls were in the right order for what I did in the code. You can change the order of the walls as long as you change it in both the code and the inspector. I did it E W N S because I like to keep both x's together and both y's together.
@@wsalevan Yeah, it was just a comment, to that you said at the start, that you have to do it that way, or it wont work. I kinda modified your script a bit, using co ordinates, checking if the Completed list has the item or the current list has the item.
Basically used Vector3(thispos.x -1, thispos.y, thispos.z) for checking if there is a node listed west of our active node