Search Unity

  1. Good news ✨ We have more Unite Now videos available for you to watch on-demand! Come check them out and ask our experts any questions!
    Dismiss Notice

DunGen - Procedural Dungeon Generation

Discussion in 'Assets and Asset Store' started by Aegon-Games, Mar 7, 2014.

  1. Sehlor

    Sehlor

    Joined:
    Feb 10, 2012
    Posts:
    199
    I think i get the hang of it and better understanding of it right now.

    I presume i need to design a hall/corridors that fits to my room's doorway and give that tileset to my line segment?

    And if you push me to the right direction how can i close my doorways if they aren't used.

    P.S. Tried when is NOT used prefab, can't get it worked.
     

    Attached Files:

  2. Drannach

    Drannach

    Joined:
    Apr 6, 2014
    Posts:
    22
    You have to use the "when not in use prefab", but you have to place it in the level, dungen will remove it when it connects 2 rooms
     
  3. DGordon

    DGordon

    Joined:
    Dec 8, 2013
    Posts:
    491
    Hey,
    Is this working with the Unity 5 beta? Also, I noticed on one of the previous pages you mentioned there is a % chance that things will fail. Will it catch it and fix it itself? I'm going to build my levels at run time ... I assume this supports that?

    If the answer is yes to everything, then I'll probably buy this instead of writing my own solution. I just need to be able to string together an arbitrary number of rooms/hallways into a dungeon. I have a few different hallway types ... is there anyway to make sure the only pieces chosen are from the corresponding set even within a single dungeon map (I want to have different "areas" within the map that can use different sets). I feel like I saw something on this but I'm at work so I can't tell.

    Thanks!,
    Dale
     
    Aegon-Games likes this.
  4. timmypowergamer

    timmypowergamer

    Joined:
    Mar 14, 2012
    Posts:
    17
    If DunGen fails to generate a dungeon layout for a given set of parameters, it will try again up to a certain number of times or (with the latest beta) forever until it succeeds. So Yes, it will catch it and fix itself. You can determine the failure % of your dungeon by using the "Analyze Dungeon" tool that comes with it, and then tweak your tiles, archetypes, and flow to improve it. The higher the failure chance, the longer it will take to successfully generate a dungeon at run time.

    As for the different hallway types, you can create different Tile Sets that contain just the tiles you want to use at any given point in the dungeon. You can also create different Archetypes which can pick and choose from any number of Tile Sets you choose, and then string Archetypes and Tile Sets together using the Flow graph. So for example, you could have an "forest" archetype for the first half of your level, and a "castle" archetype for the second half. Then somewhere in the middle you can tell it to place a transition tile to go between them. You can also specify different "socket types" for the doorways you define, which can further control which tiles can get connected. So a door marked as "large" will never get connected to a door marked as "default", etc.

    Don't know about Unity 5 myself, but I see no reason why DunGen shouldn't work with it. Maybe someone else with access to the beta can confirm. :)
     
    Aegon-Games likes this.
  5. Binary42

    Binary42

    Joined:
    Aug 15, 2013
    Posts:
    168
    Jepp! :)
     
    Aegon-Games likes this.
  6. DGordon

    DGordon

    Joined:
    Dec 8, 2013
    Posts:
    491
    Thanks guys. I picked it up ... so far its awesome :).
     
  7. Binary42

    Binary42

    Joined:
    Aug 15, 2013
    Posts:
    168
    I've put up a little demo with Unity 5 beta.

    mutantWatch.jpg
    In fact this is for Navmesh and wandering AI testing so don't expect to much, but you can see DunGen in action.
    'G' generates a new Dungeon. DunGen is blazing fast (few hundred ms), but the Navmesh generation takes some time.
    'C' Cycles through Mutants.

    Grab it here (168 MB): https://www.dropbox.com/s/5r8rryecxdz1234/MutantWatch.zip?dl=0

    AegonGames ( Dan? :) ) when will you look into the DoorSocket and Key issues? I badly need the sockets for vents aka secret doors and if you're lucky its just the same giving-up-early problem like before. Keys are mandatory.

    When those problems are solved i could finally plug something playable together and i promise to stop bothering you. ;)
     
    Last edited: Jan 10, 2015
    Drannach and Gekigengar like this.
  8. DSebJ

    DSebJ

    Joined:
    Mar 30, 2013
    Posts:
    101
    Nice! I'm using the same set peices with DunGen :)

    How have you setup the rooms to get such a quick generation? Any tips?
     
  9. Binary42

    Binary42

    Joined:
    Aug 15, 2013
    Posts:
    168
    Sure, all it needs is 100% generation success rate. ;)
    - Use a grid
    - Update DunGen to the leatest beta
    - Use a 4x4 units grid as basis and segmentCorner_A as smallest room and as ruler. The doorways should be exactly at 4 or -4 at segmentCorner_A.
    - The pack is missing some half-pieces, you can see in the shot how i had to scale the doorway to make the halls fit into the grid.
    - Use a grid
     
    Last edited: Jan 11, 2015
  10. Count-Swagula

    Count-Swagula

    Joined:
    Feb 2, 2014
    Posts:
    9
    This looks pretty cool.

    I just have a few questions:

    • Is there a way to have "special rooms" like a randomly (or specifically) placed item shop?
    • Is there a way to spawn enemies or power ups in certain types of rooms?
    • Will this work with plygame?
     
  11. timmypowergamer

    timmypowergamer

    Joined:
    Mar 14, 2012
    Posts:
    17
    For sure. You can tell it to place a specific tile (or random tile from a specific tile set) at any point along the dungeon flow. You can also tell it to use certain tiles to "cap" a branch path, so you could make it place an item shop at a dead end away from the main path to reward player for exploring, for example.

    Absolutely. Inside of a tile you can set up "Local Prop Sets" which will pick a random number of props to place in the room. The props can be anything, so you could place monsters and items and say "I want 2-4 monsters in this room, and 0-1 pickups". You can also use "Global Prop Sets" if you need more control over the total number of enemies and power-ups in your dungeon. With a global prop set you could say " I want 12 enemies in this level, and 2 power-ups". You place them ahead of time in your tiles and DunGen picks however many to keep and removes the rest.

    Never used it myself, but looking at it I see no reason why not. You might run into problems if you are trying to use nav-meshes for AI because you will have to generate them at run-time (which can be slow), but as Binary42 has shown above, it's do-able.
     
    Aegon-Games and Binary42 like this.
  12. Sehlor

    Sehlor

    Joined:
    Feb 10, 2012
    Posts:
    199
    Can i use ProGrids 2.0 instead of EasySnap?

    And if i can, which grid size should i choose?
     
  13. Binary42

    Binary42

    Joined:
    Aug 15, 2013
    Posts:
    168
    Unity has even a very simple build in snaping tool (see link). If you want to master constructing and become fast check out unity's vertex snap too. http://docs.unity3d.com/Manual/PositioningGameObjects.html

    It doesnt matter what grid u use, what matters is that you stick to it. U might could do the following:
    A floor tile (Ground01) is 5x5, the smalest room you could build, based on the walls that are available, would be 3x3 = 9 Ground01 Tiles. If u start at 0,0,0 with placing the tiles it would be half plus one tile in each direction to the edge of the room. So your grid would be based on 5+2.5 = 7.5. What leads to room dimensions of 15x15 Units. Based on that you can go on and do a long room 30x15, a small corridor 15x(whatever less then 15) a long corridor 30x(whatever less then 15) and so on. As long as the doorways are on the grid.

    But now you have the problem that the walls get double placed into another, so you have to deal with that and maybe scale the floor tiles (to grid of 7.75) or scale the center wall pieces so the edges of walls and floor would align. If you want double walls at all. Or you can use a pack that offers complete half walls like the piece Dungeon03_c is made, with that you just place the front side and (if there is) the next room places the back side. But that maybe wont fit well for an Top-Down. So it all depends what you want to do in the end. Even the grid ( but you have to stick to it ;) ).

    It took me almost a week to figure out how to make a "good" room. So don't give up!

    Oh, and there is always the Straighten slider available in the Archetype for cheating. ;)
     
    Last edited: Jan 13, 2015
    Aegon-Games likes this.
  14. Aegon-Games

    Aegon-Games

    Joined:
    Mar 7, 2014
    Posts:
    473
    Sorry I haven't responded in a while, still really busy. I should be able to spend some more time on DunGen after the next few days. Thanks to everyone who answered questions while I was gone, they were pretty much the same answers I would have given :)

    Looking into those is the first thing on my list, hopefully I'll be able to work on it by Thursday/Friday. Again, sorry for the delay.

    And yeah, my name's Dan, feel free to call me that if you want. I'm not sure why I went all formal with the forum username :p
     
    Binary42 likes this.
  15. Count-Swagula

    Count-Swagula

    Joined:
    Feb 2, 2014
    Posts:
    9
    Thanks. I'm still unfamiliar with the overall systems but I just wanted some clarification before I bought it. Is a tile the same thing as a room in a general sense?

    Sweet. I can code a lot of the logic myself but as we all know, time is money and I don't have an infinite amount of time on this project I plan to work on. I'm glad to hear that I can have specific enemy sets spawn in various rooms.


    Yeah I'm sure there is a way around it. I will look into that further. Thanks again.

    Also, I'm glad to hear the lock and key system is being worked on.
     
  16. timmypowergamer

    timmypowergamer

    Joined:
    Mar 14, 2012
    Posts:
    17
    In the general sense, yes. A tile is a room. But they can be (almost) any size/shape/configuration you want. So tiles can also make the hallways that join your rooms, or you can set it up so that many different tiles join to form a larger space. It all depends on how you configure the different parts that go into DunGen. It's really quite flexible :)
     
  17. Sehlor

    Sehlor

    Joined:
    Feb 10, 2012
    Posts:
    199
    I grip a pretty good handle with DunGen.

    My goal is construct an outdoor random map ( dungeon type ) or at least give the feel like that.

    I'm gonna try things. But any suggestion to where i'm headed?

    Thanks for great plugin!
     
  18. Binary42

    Binary42

    Joined:
    Aug 15, 2013
    Posts:
    168
    After all i'm redoing my rooms again ( i stopped counting ) since the doors didn't spawn nicely. Scaling here and there and remake pieces that wont fit at all.

    I wan't a "DunGen certified"- Badge for asset providers. x)
     
  19. MIK3K

    MIK3K

    Joined:
    Sep 10, 2014
    Posts:
    144
    That is . . . Wow! Trying to learn how people are doing this crazy stuff - Are the navigation and minimap asset store items?
     
  20. Binary42

    Binary42

    Joined:
    Aug 15, 2013
    Posts:
    168
    The Minimap are blue boxes enclosing the room tiles, only visible to the minimap cam.
    The Naviagtion/AI i use is Rival Theory's Rain. It's free and awesome. :)
     
  21. MIK3K

    MIK3K

    Joined:
    Sep 10, 2014
    Posts:
    144
    Thanks for sharing that Binary42! I'm starting to think I should have picked an easier hobby where my brain doesn't have to work so much. Your demo is very impressive and inspiring.
     
  22. ashwinFEC

    ashwinFEC

    Joined:
    May 19, 2013
    Posts:
    35
    I have modified Dungen to force a tile to make a U-turn. So that the next Doorway picked will be on the same side as the entrance Doorway. Here is the code if you are interested

    Tile.cs
    Add three new variables
    Code (CSharp):
    1. public class Tile : MonoBehaviour
    2. {
    3. [...]
    4.    public bool forceUturn = false;
    5.    public float forceUturnChance = 0.0f;
    6.    public bool DoNotAttachBranchTiles = false;
    7. [...]
    TileInspector.cs
    Expose the variables in the editor
    Code (CSharp):
    1.  public class TileInspector : UnityEditor.Editor
    2. {
    3.         public override void OnInspectorGUI()
    4.         {
    5.            [...]
    6.             tile.forceUturn = EditorGUILayout.Toggle("Increase chances of U-turn", tile.forceUturn);
    7.             tile.forceUturnChance = EditorGUILayout.Slider("U-Turn Chance", tile.forceUturnChance, 0f, 1.0f);
    8.             tile.DoNotAttachBranchTiles = EditorGUILayout.Toggle("Do Not Branch From this tile", tile.DoNotAttachBranchTiles);
    9.  
    10.            [...]
    11.         }
    12. }
    TilePlacementData.cs
    Add two new parameters to PickRandomDoorway method, add a new random variable, add an extra condition, uturnChance < 1f, and extra add code
    Code (CSharp):
    1. public Doorway PickRandomDoorway([...], bool uturn = false, float uturnChance = 0f)
    2. {
    3. [...]
    4.             double rndUturn = randomStream.NextDouble();
    5.  
    6.  
    7.             // Try to pick the opposing doorway, based on archetype's StraightenChance
    8.             if (isOnMainPath && [...] && uturnChance < 1f)
    9.             {
    10.                 [...]
    11.             }
    12.  
    13.             if (uturn && UsedDoorways.Count == 1 && rndUturn < uturnChance)
    14.             {
    15.                 foreach (Doorway d in UnusedDoorways)
    16.                 {
    17.                     if (UsedDoorways[0].transform.forward == d.transform.forward)
    18.                         return d;
    19.                 }
    20.             }
    21.  
    22. [...]
    23. }
    24.  
    DungeonGenerator.cs
    Add extra condition in the first if check in the foreach loop in GenerateBranchPaths
    Add the extra variables when calling PickRandomDoorway
    Code (CSharp):
    1.  
    2. protected virtual void GenerateBranchPaths()
    3. {
    4. [...]
    5.        if (tile.Archetype == null || tile.DoNotAttachBranchTiles)
    6.             continue;
    7. [...]
    8. }
    9.  
    10. protected virtual Tile AddTile([...])
    11. {
    12. [...]
    13.     Doorway fromDoorway = (attachTo == null) ? null : attachTo.Placement.PickRandomDoorway(RandomStream, true, archetype, attachTo.forceUturn, attachTo.forceUturnChance );
    14.  
    15. [...]
    16. }
    Don't forget to add Tile.cs to the root of your tile.
     
    Last edited: Jan 21, 2015
    AlexSledge and Binary42 like this.
  23. Aegon-Games

    Aegon-Games

    Joined:
    Mar 7, 2014
    Posts:
    473
    I'm really sorry this took so long. I've got a new build ready now, hopefully it fixes both of your issues. I haven't tested the fix to the DoorSocket issue much at all (I don't have a dungeon set up that uses multiple sockets extensively), but DunGen was just giving up if it didn't find any Tiles with that socket type in the chosen TileSet; that's been fixed. You should now be able to spawn multiple keys for each lock (set up through the KeyManager asset).

    I'm still busy with other things right now so I'm not back to my usual working time for DunGen yet, but let me know if this build doesn't help and I'll try to fix it as soon as I can. Thanks for your patience.


    Version 2.5.2 (Beta) - Download
    - Users should notice a large improvement in success rate when generating dungeons.
    - DunGen will keep trying until it succeeds when the project is built (can still fail in the editor as a safety net to prevent infinite loops for invalid dungeons)
    - Fixed an issue causing bounding boxes to sometimes be calculated incorrectly
    - Doorways should no longer have multiple door prefabs assigned to them if the doorways were connected by overlapping
    - Added a Straighten slider to the DungeonArchetype that controls the likelihood that the main path generated will be a straight line
    - [NEW] Multiple keys can now be spawned for a single lock. In the KeyManager asset, each key has a "Keys per Lock" value
    - [NEW] DunGen should now retry to place a Tile when none of those in the TileSet have a socket of the correct type
     
  24. kilik128

    kilik128

    Joined:
    Jul 15, 2013
    Posts:
    882
    i always fight with Doorway setup now in 2d any way to know where setup fall
     
  25. Binary42

    Binary42

    Joined:
    Aug 15, 2013
    Posts:
    168
    Sweeeet! \o/
    I'm getting now 46% success for the previously described test setup with mixed doorways (was 4%). Awesome! I think that could be considered as solved. :)

    For the key's: Im trying this with the demo dungeon, 40 rooms so there would be plenty key spawn points. I removed all line segment lock settings and keys but the red one. At the Line segment for the Castle Dungeon Archetype, i set keys to red, Locks also to red key and count to 10 (no range so it's simpler to explain). What i'd expect it is to spawn 10 red keys and 10 red locks. It's still just one key+lock that gets spawned.

    Thanks Dan!

    @ MIK3K, just don't give up! That's all what it takes.

    Edit: Just found this Extra Credits - Roguelike Returns :D
     
    Last edited: Jan 21, 2015
  26. ashwinFEC

    ashwinFEC

    Joined:
    May 19, 2013
    Posts:
    35
    I've have managed to decrease the amount of failures and time needed for generation significantly. Yesterday I had a shower thought. I was wondering what would happen when in the for loop at the end of GenerateMainPath() when AddTile returns null, instead of starting the path from scratch I delete the last successful tile and continue to generate the path from that point on.

    So if it fails at tile# 196, instead of deleting all the previous 195 tiles you only delete 1 tile and start generating tile# 195. So you take one step forward and if it fails you take two steps back instead of starting from the beginning.

    To my surprise it worked out. I ran my code (see below) in the demo analyzer scene with path length of 60-70, 40 iterations and 20 max attempts and here are the results (running on a 2011 iMac with 2.5GHz i5):

    Before (2.5.2 Beta)


    After


    As you can see the time has more than halved and the number of failures are down to zero. Though AegonGames should definitely have a look at my code, because I am not sure if I am removing the tile, the connections and the doors in the right way. I don't have prefab doors in my dungeon so I don't know if it is working correctly.

    Dungeon.cs
    Add two new functions
    Code (CSharp):
    1.  
    2. [...]
    3.    internal void RemoveLastConnection()
    4.         {
    5.             var conn = connections.Last();
    6.  
    7.             Doorway a = conn.A;
    8.             Doorway b = conn.B;
    9.  
    10.             a.RemoveUsedPrefab();
    11.             b.RemoveUsedPrefab();
    12.  
    13.             a.Tile.Placement.UnusedDoorways.Add(a);
    14.             a.Tile.Placement.UsedDoorways.Remove(a);
    15.  
    16.             b.Tile.Placement.UnusedDoorways.Add(b);
    17.             b.Tile.Placement.UsedDoorways.Remove(b);
    18.  
    19.             //var door = doors.Last();
    20.               if (doors.Count > 0)
    21.                doors.RemoveAt(doors.Count - 1);
    22.  
    23.             connections.Remove(conn);
    24.         }
    25.  
    26.         internal void RemoveTile(Tile tile)
    27.         {
    28.             if (allTiles.Contains(tile))
    29.                 allTiles.Remove(tile);
    30.  
    31.             if (mainPathTiles.Contains(tile))
    32.                 mainPathTiles.Remove(tile);
    33.  
    34.             if (branchPathTiles.Contains(tile))
    35.                 branchPathTiles.Remove(tile);
    36.  
    37.             Destroy(tile.gameObject);
    38.  
    39.  
    40.         }
    41. [...]
    42.  
    DungeonGenerator.cs
    Replace the for loop at the end of the GenerateMainPath() method with the code below
    Code (CSharp):
    1.    
    2.       protected virtual bool GenerateMainPath()
    3.       {
    4. [...]
    5.  
    6.             /* if you have a low variety of tiles the generator might constantly pick
    7.              * the same tiles during a retry and thus always fail
    8.              * these counters will prevent an infiniteloop
    9.              */
    10.             int tileRetryCount = 0;
    11.             int totalForLoopRetryCount = 0;
    12.  
    13.             for (int j = 0; j < tiles.Count; j++)
    14.             {
    15.                 var tile = AddTile((j == 0) ? null : currentDungeon.MainPathTiles[j - 1],
    16.                                     tiles[j],
    17.                                     j / (float)(tiles.Count - 1),
    18.                                     archetypes[j]);
    19.  
    20.                 // if no tile could be generated delete last successful tile and retry from previous index
    21.                 // else return false
    22.                 if (j > 5 && tile == null && tileRetryCount < 5 && totalForLoopRetryCount < 20)
    23.                 {
    24.                     currentDungeon.RemoveLastConnection();
    25.                     currentDungeon.RemoveTile(currentDungeon.MainPathTiles[j - 1]);
    26.          
    27.                     j -= 2; // -2 because loop adds 1
    28.                     tileRetryCount++;
    29.                     totalForLoopRetryCount++;
    30.  
    31.                 }
    32.                 else if (tile == null)
    33.                 {
    34.                     return false;
    35.  
    36.                 }
    37.                 else
    38.                 {
    39.                     tile.Node = nodes[j];
    40.                     tile.Line = lines[j];
    41.                     tileRetryCount = 0;
    42.                 }
    43.  
    44.             }
    45.    
    46. [...]
    47.         }
    48.  
     
    Last edited: Jan 22, 2015
    Drannach, MIK3K, Binary42 and 2 others like this.
  27. Binary42

    Binary42

    Joined:
    Aug 15, 2013
    Posts:
    168
    "Cool cool, cool cool cool" - Abed Nadir

    I've briefly tested your code and i can't see problems with connections. I just had to use DestroyImmediate instead of Destroy to have it run in the editor. On top the speed gain my reference mixed-doorway-test-setup builds now to 100% success ( was about 45% ).

    If i had a vote, i'd vote to take ashwinFEC's changes into the code base. :)

    Edit (after the like ;) ):
    Though, it scales badly with dungeon size if you have many many different tiles (exponentially time increase). Imagine you have tiles evenly ranging in size from 1-10.
    Worst case: last 10 tiles placed where size 1. Chances are good (90%) a tile for retry will be picked that is bigger than 1 and will fail. You go back, tile size 1 and 2 will fit now, still chances to fail are 80%. next step back 70%. And so on.

    It's still a good idea, but it could be tweaked at that point. I have no idea atm myself, except for "go back 1/3 of already placed tiles" maybe. But that wold make the worst case just less likley, on the other end, who should ever play through 200 rooms?
     
    Last edited: Jan 22, 2015
    hopeful likes this.
  28. ashwinFEC

    ashwinFEC

    Joined:
    May 19, 2013
    Posts:
    35
    @Binary42 Thats why I let the loop in GenerateMainPath fail after 5 consecutive null tiles and fail after 20 times retreating the path back (these numbers could still be tweaked).

    There is of course room for improvement, but it works for what I want to do. I have a dungeon with varying tile sizes and I am able to build pretty big dungeons like 80 main rooms 80 branch rooms because of the changes. With the normal code it would have failed even with 200 retries. But in reality my dungeons will be much smaller and I will benefit from the faster generation times.
     
  29. Aegon-Games

    Aegon-Games

    Joined:
    Mar 7, 2014
    Posts:
    473
    Oops, I misunderstood what your issue was. I thought you wanted to be able to spawn multiple keys for a single doorway. I didn't realize that DunGen was just not placing the correct number of keys & locks (if above 1). Well, the multiple keys thing is there for anyone who wants it :p I'll take a look and see if I can get that bug fixed.


    That sounds pretty fantastic. I didn't think that back-tracking one room would make so much of a difference. I'd love to incorporate your code into DunGen if that's all right.

    There are a couple more things I could do to improve the dungeon success rate; the biggest one being to improve the way DunGen retries things. Right now it's a really naive implementation, it just picks a new option at random, so there's nothing to stop it picking the same option multiple times. This also means that it will retry the specified number of times even if there aren't that many options to choose from (e.g. it failed on all four doorways, but the MaxAttemptCount is 5, so it'll try again).
     
    Drannach, MIK3K and hopeful like this.
  30. kenlem

    kenlem

    Joined:
    Oct 16, 2008
    Posts:
    1,617
    I'm having trouble getting DunGen to work on iOS because of LINQ. I'm using the latest beta. Any suggestions?
     
  31. kenlem

    kenlem

    Joined:
    Oct 16, 2008
    Posts:
    1,617
    I swapped linq for LINQ for iOS from the Asset Store and have the same error.


    ExecutionEngineException: Attempting to JIT compile method 'System.Linq.Enumerable/PredicateOf`1<int>:.cctor ()' while running with --aot-only.


    Rethrow as TypeInitializationException: An exception was thrown by the type initializer for PredicateOf`1
    at DunGen.DungeonGenerator.PostProcess () [0x00000] in <filename unknown>:0
    at DunGen.DungeonGenerator.InnerGenerate (Boolean isRetry) [0x00000] in <filename unknown>:0
    at DunGen.DungeonGenerator.InnerGenerate (Boolean isRetry) [0x00000] in <filename unknown>:0
    at DunGen.DungeonGenerator.OuterGenerate () [0x00000] in <filename unknown>:0
    at DunGen.DungeonGenerator.Generate () [0x00000] in <filename unknown>:0
    at GameManager.GenerateDungeon () [0x00000] in <filename unknown>:0
    at GameManager.Start () [0x00000] in <filename unknown>:0
    (Filename: Line: -1)

    It looks like everything ran until the postprocessing step. Any suggestions?
     
  32. ashwinFEC

    ashwinFEC

    Joined:
    May 19, 2013
    Posts:
    35
    @AegonGames Yes please add my code to the DunGen code, other users who don't read the forum should should also benefit from it.
     
    Drannach, Binary42 and MIK3K like this.
  33. Aegon-Games

    Aegon-Games

    Joined:
    Mar 7, 2014
    Posts:
    473
    Again, sorry for the late replies everyone.

    I'm not noticing any problems with 2D with the (admittedly limited) demo scene. Can you explain what exactly is going wrong?


    I've replaced the LINQ in that function in the newest build but I'm not sure if it is going to work since I can't test on iOS. I think I'm just doing the same as the LINQ expression was (just with 12 lines instead of 1) so it might still fail to compile, please let me know if it still doesn't work and I'll try to think of an alternate way to write it.


    Thanks! I've included your change pretty much verbatim. I might go back and expose some of the parameters to the editor later, but it seems to work really well as-is.


    There was a bug causing DunGen to always attempt to place one locked door in a segment regardless of the number that you specify. I've fixed this in the newest build. Unfortunately, while DunGen now can generate the correct number of locked doors, it rarely does in my experience. There are two main reasons that I can think of for this:

    1. Not enough key spawn locations - easy enough to improve upon
    2. A doorway was picked that was so close to the start of the segment that there are few tiles to place the key in (in order to guarantee that the player will have the key in time, only tiles prior to the locked door are considered viable locations for a key), leading back to problem #1

    I don't have a setup specifically catered to supporting multiple locked doors and keys, so maybe your experience will differ from mine; otherwise, I think I might need to re-write a lot of the lock & key placement logic.



    Version 2.5.2 (Beta) - Download
    - Users should notice a large improvement in success rate when generating dungeons.
    - DunGen will keep trying until it succeeds when the project is built (can still fail in the editor as a safety net to prevent infinite loops for invalid dungeons)
    - Fixed an issue causing bounding boxes to sometimes be calculated incorrectly
    - Doorways should no longer have multiple door prefabs assigned to them if the doorways were connected by overlapping
    - Added a Straighten slider to the DungeonArchetype that controls the likelihood that the main path generated will be a straight line (thanks to Binary42)
    - Doorways with different sockets will no longer be connected when overlapping
    - Multiple keys can now be spawned for a single lock. In the KeyManager asset, each key has a "Keys per Lock" value
    - DunGen should now retry to place a Tile when none of those in the TileSet have a socket of the correct type
    - [NEW] Users should notice a further large improvement in success rate when generating dungeons; in addition to shorter generation times (thanks to ashwinFEC)
    - [NEW] DunGen should now correctly try to add the specified number of locked doors to a dungeon segment. NOTE: This still rarely produces desired results


    Edit: I should probably push this version to the Asset Store some time soon, people who don't download the beta versions are missing out on a lot...
     
    c-Row likes this.
  34. hopeful

    hopeful

    Joined:
    Nov 20, 2013
    Posts:
    5,194
    I was wondering when you were going to publish some of these fixes / new features. :)
     
  35. Aegon-Games

    Aegon-Games

    Joined:
    Mar 7, 2014
    Posts:
    473
    I didn't realize just how long it had been since I'd pushed a new version to the Asset Store :p. Every time I think I'm done with a version, a new bug or possible feature is brought to my attention and I think "I'll just do this one last thing".

    2.5.2 has two (or three if you're using multiple doorway socket types) major improvements to success chance; that alone means most DunGen users are missing out on a lot by not using the beta version, not to mention the important bug fixes since 2.5.0.

    Anyway, I think I'll submit the new version to the Asset Store on Friday, hopefully that'll give enough time to find & fix any potential major issues I've introduced in the new build. In the future, I'll try to keep the beta duration of a new version down to no longer than a month, more likely 1-2 weeks.
     
    hopeful likes this.
  36. Alphalpha

    Alphalpha

    Joined:
    Oct 9, 2013
    Posts:
    71
    Couldn't you use the same 'rollback' logic provided by ashwinFEC to retry placing locked doors if it can't generate enough keys? I guess it would depend on whether the doorways are selected while the dungeon layout is being generated or afterwards.
     
  37. Binary42

    Binary42

    Joined:
    Aug 15, 2013
    Posts:
    168
    Heh, now that i have memorized my InvoNr. ;)
    The improvements of the last weeks make dungeon generation indeed a lot easier, faster and predictable.

    Keys are working as expected now.
     
  38. Aegon-Games

    Aegon-Games

    Joined:
    Mar 7, 2014
    Posts:
    473
    The locks are placed in a separate pass after the layout is generated, so I absolutely could rollback and try again. That's probably going to be the solution I go with, although I'm going to consider some other solutions in the meantime. The solution won't make it into 2.5.2 though.


    As promised, the newest build (2.5.2) has been submitted to the Asset Store so it should show up there in the next few days.
     
  39. bigdaddio

    bigdaddio

    Joined:
    May 18, 2009
    Posts:
    219
    I just ran through the forum again. I did not see an answer to a question I have. Is there a way to get the adjoining tile? Say I have 4 doors A, B, C, D. Is there a way I can find the tile attached to each? The reason is I want to trigger an action to happen when I go into a doorway. In my room I have a door, when that door is activated I'd like to send a message or something to the attached tile. Doorway exposes the Tile I am in, but from there I get lost.
     
  40. Aegon-Games

    Aegon-Games

    Joined:
    Mar 7, 2014
    Posts:
    473
    If you want to do something with all doorways for the tile, you should be able to loop through tile.Placement.UsedDoorways

    If you just want to get the tile that a doorway leads to, you'll have to go through the graph and do something like this:

    Code (CSharp):
    1. public Tile GetAdjacentTile(DungeonGenerator generator, Doorway fromDoorway)
    2. {
    3.     foreach (var conn in generator.CurrentDungeon.Connections)
    4.     {
    5.         if (conn.A == fromDoorway)
    6.             return conn.B.Tile;
    7.         else if (conn.B == fromDoorway)
    8.             return conn.A.Tile;
    9.     }
    10.  
    11.     return null;
    12. }
     
  41. Binary42

    Binary42

    Joined:
    Aug 15, 2013
    Posts:
    168
    Bugreport ( yay! ;) )
    I occasionally get these errors

    KeyNotFoundException: The given key was not present in the dictionary.
    System.Collections.Generic.Dictionary`2[DunGen.Tile,DunGen.DungeonGraphNode].get_Item (DunGen.Tile key) (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System.Collections.Generic/Dictionary.cs:150)
    DunGen.DungeonGraph..ctor (DunGen.Dungeon dungeon) (at Assets/DunGen/Code/Graph/DungeonGraph.cs:28)
    DunGen.Dungeon.PostGenerateDungeon (DunGen.DungeonGenerator dungeonGenerator) (at Assets/DunGen/Code/Dungeon.cs:42)
    DunGen.DungeonGenerator.PostProcess () (at Assets/DunGen/Code/DungeonGenerator.cs:688)
    DunGen.DungeonGenerator.InnerGenerate (Boolean isRetry) (at Assets/DunGen/Code/DungeonGenerator.cs:199)
    DunGen.DungeonGenerator.OuterGenerate () (at Assets/DunGen/Code/DungeonGenerator.cs:102)
    DunGen.DungeonGenerator.Generate () (at Assets/DunGen/Code/DungeonGenerator.cs:82)
    DunGen.Editor.DungeonGeneratorWindow.GenerateDungeon () (at Assets/DunGen/Code/Editor/Windows/DungeonGeneratorWindow.cs:38)
    DunGen.Editor.DungeonGeneratorWindow.OnGUI () (at Assets/DunGen/Code/Editor/Windows/DungeonGeneratorWindow.cs:29)
    System.Reflection.MonoMethod.Invoke (System.Object obj, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System.Reflection/MonoMethod.cs:222)

    ArgumentException: An element with the same key already exists in the dictionary.
    System.Collections.Generic.Dictionary`2[Doorway,DunGen.Key].Add (.Doorway key, DunGen.Key value) (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System.Collections.Generic/Dictionary.cs:404)
    DunGen.DungeonGenerator.PlaceLocksAndKeys () (at Assets/DunGen/Code/DungeonGenerator.cs:829)
    DunGen.DungeonGenerator.PostProcess () (at Assets/DunGen/Code/DungeonGenerator.cs:689)
    DunGen.DungeonGenerator.InnerGenerate (Boolean isRetry) (at Assets/DunGen/Code/DungeonGenerator.cs:199)
    DunGen.DungeonGenerator.OuterGenerate () (at Assets/DunGen/Code/DungeonGenerator.cs:102)
    DunGen.DungeonGenerator.Generate () (at Assets/DunGen/Code/DungeonGenerator.cs:82)
    DunGen.Editor.DungeonGeneratorWindow.GenerateDungeon () (at Assets/DunGen/Code/Editor/Windows/DungeonGeneratorWindow.cs:38)
    DunGen.Editor.DungeonGeneratorWindow.OnGUI () (at Assets/DunGen/Code/Editor/Windows/DungeonGeneratorWindow.cs:29)
    System.Reflection.MonoMethod.Invoke (System.Object obj, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System.Reflection/MonoMethod.cs:222)

    IndexOutOfRangeException: Array index is out of range.
    DunGen.DungeonGenerator.LockDoorway (.Doorway doorway, DunGen.Key key, DunGen.KeyManager keyManager) (at Assets/DunGen/Code/DungeonGenerator.cs:903)
    DunGen.DungeonGenerator.PlaceLocksAndKeys () (at Assets/DunGen/Code/DungeonGenerator.cs:895)
    DunGen.DungeonGenerator.PostProcess () (at Assets/DunGen/Code/DungeonGenerator.cs:689)
    DunGen.DungeonGenerator.InnerGenerate (Boolean isRetry) (at Assets/DunGen/Code/DungeonGenerator.cs:199)
    DunGen.DungeonGenerator.OuterGenerate () (at Assets/DunGen/Code/DungeonGenerator.cs:102)
    DunGen.DungeonGenerator.Generate () (at Assets/DunGen/Code/DungeonGenerator.cs:82)
    DunGen.Editor.RuntimeAnalyzer.Update () (at Assets/DunGen/Code/Analysis/RuntimeAnalyzer.cs:81)

    And an easily fixed one appears only when using the Generate GUI:

    Destroy may not be called from edit mode! Use DestroyImmediate instead.
    Also think twice if you really want to destroy something in edit mode. Since this will destroy objects permanently.
    UnityEngine.Object:Destroy(Object)
    DunGen.Dungeon:RemoveTile(Tile) (at Assets/DunGen/Code/Dungeon.cs:138)
    DunGen.DungeonGenerator:GenerateMainPath() (at Assets/DunGen/Code/DungeonGenerator.cs:339)
    DunGen.DungeonGenerator:InnerGenerate(Boolean) (at Assets/DunGen/Code/DungeonGenerator.cs:188)
    DunGen.DungeonGenerator:OuterGenerate() (at Assets/DunGen/Code/DungeonGenerator.cs:102)
    DunGen.DungeonGenerator:Generate() (at Assets/DunGen/Code/DungeonGenerator.cs:82)
    DunGen.Editor.DungeonGeneratorWindow:GenerateDungeon() (at Assets/DunGen/Code/Editor/Windows/DungeonGeneratorWindow.cs:38)
    DunGen.Editor.DungeonGeneratorWindow:OnGUI() (at Assets/DunGen/Code/Editor/Windows/DungeonGeneratorWindow.cs:29)
    UnityEditor.DockArea:OnGUI()
     
  42. SPG_John

    SPG_John

    Joined:
    Aug 30, 2013
    Posts:
    4
    Great asset, just started getting into this! I noticed one error that was popping up while testing the DungeonGenerator from inside the editor when generating a new dungeon (should be fine at runtime.) I believe you need to update the DungeonGenerator.cs file, inside the function RemoveTile to handle GameObject destruction when running in the Editor:

    Original:
    Code (CSharp):
    1.         internal void RemoveTile(Tile tile)
    2.         {
    3.             if (allTiles.Contains(tile))
    4.                 allTiles.Remove(tile);
    5.  
    6.             if (mainPathTiles.Contains(tile))
    7.                 mainPathTiles.Remove(tile);
    8.  
    9.             if (branchPathTiles.Contains(tile))
    10.                 branchPathTiles.Remove(tile);
    11.  
    12.             Destroy(tile.gameObject);
    13.         }

    Updated:

    Code (CSharp):
    1.         internal void RemoveTile(Tile tile)
    2.         {
    3.             if (allTiles.Contains(tile))
    4.                 allTiles.Remove(tile);
    5.  
    6.             if (mainPathTiles.Contains(tile))
    7.                 mainPathTiles.Remove(tile);
    8.  
    9.             if (branchPathTiles.Contains(tile))
    10.                 branchPathTiles.Remove(tile);
    11.  
    12.             if (Application.isEditor) {
    13.                 DestroyImmediate(tile.gameObject);
    14.             } else {
    15.                 Destroy(tile.gameObject);
    16.             }
    17.         }

    Otherwise you end up having some overlapping tiles in your resulting dungeon, which can lead to collision issues as well as general visual problems.
     
  43. Aegon-Games

    Aegon-Games

    Joined:
    Mar 7, 2014
    Posts:
    473
    Thanks for the bug reports. Other than the "DestoyImmediate" one, I haven't been able to reproduce them, but have found an error in my logic for most so I think they're fixed.

    One of those exceptions was caused by trying to access a random element from an empty list (when trying to place a lock in a Tile from a TileSet with no locked door prefabs). DunGen now ignores doorways from such Tiles. But this means that you'll have no warning if you try to use the lock & key system but haven't added locked door prefabs to any of your Tile Sets, it just won't work.

    I haven't been able to find what's causing this one though:
    I couldn't reproduce it at all with the demo scene.



    Version 2.5.3 (Beta) - Download
    - [NEW] DunGen should no longer try to apply a lock to the same door twice, causing an exception to be thrown
    - [NEW] Doorways with no possible "locked door prefab" will no longer be considered when adding locks
    - [NEW] In-editor dungeons will once again generate correctly
    - [NEW] Dungeons should now be generated in the local coordinate space of it's root GameObject, rather than at the world-space origin
     
    hopeful likes this.
  44. Binary42

    Binary42

    Joined:
    Aug 15, 2013
    Posts:
    168
    Hi that Bug happens at approx. 5% chance while generating dungeons and got introduced with the asset store update.
    It trys to access non existent doorways, but since it happens in a foreach loop which would return only valid data the bug maybe is a syncing problem. Do you properly update the Data when falling into the new retry logic?

    Another problem with that new Logic is that it seems to overrule all weights and curves that where set for the flow.
     
  45. Aegon-Games

    Aegon-Games

    Joined:
    Mar 7, 2014
    Posts:
    473
    I don't see any problems with the backtrack logic that would cause the data to be incorrect (but to be sure, you could go into the DungeonGenerator class and set AllowBacktracking to false). I thought I might have found what was wrong since I wasn't calling ExposeRoomProperties() before trying to access the public read-only lists; but it turns out that ReadOnlyCollection actually doesn't need to be re-created when you change the backing field so the data is always up-to-date. I suppose at least I've learned something new, but I'm no closer to fixing the error.

    I still wasn't able to reproduce that error with the demo scene; even after increasing the dungeon length (for a greater chance of needing to backtrack) and holding the 'R' key for several minutes. I must have generated close to 1000 dungeons and it didn't throw that exception once. Do you get that exception using the demo scene?
     
  46. bigdaddio

    bigdaddio

    Joined:
    May 18, 2009
    Posts:
    219
    Sweet this works great, thanks.
     
  47. kerafrymm

    kerafrymm

    Joined:
    Jan 20, 2013
    Posts:
    21
    Looking to buy this but have a pretty basic question:

    Can this be used purely with 2D artwork/tiles, or does it only work with meshes?

    Sorry, don't really know how to search a thread.
     
  48. Aegon-Games

    Aegon-Games

    Joined:
    Mar 7, 2014
    Posts:
    473
    It should work fine with 2D sprites. There's a (very) simple demo scene for 2D dungeons included.
     
  49. Gekigengar

    Gekigengar

    Joined:
    Jan 20, 2013
    Posts:
    460
    I have been eye ogling this asset since long ago.

    I saw that this went on sale for 24 hours, sadly my card is not working at that time. :(

    Since then, it never went on sale again.

    Any plans on when the next sale will be?
     
  50. Binary42

    Binary42

    Joined:
    Aug 15, 2013
    Posts:
    168
    The asset authors can just choose to generally participate at sales or not. It is totally up to the assetstore when and what items are up for the sale. But DunGen is totally worth the regular price. :)
     
    Gekigengar likes this.
unityunity