Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Question How to avoid loading times in procedurally generated dungeons?

Discussion in 'Editor & General Support' started by Cuddles_, Dec 2, 2021.

  1. Cuddles_

    Cuddles_

    Joined:
    Jun 20, 2021
    Posts:
    3
    Hi! Aspiring gamedev learning the ropes here. I've been working on an isometric dungeon crawler for a handful of months and have run into a problem I'm not quite sure how to solve. I'm hoping someone here may have some insight.

    Up until recently, each of my levels was built manually in its own scene, with a door at the end that would load the next scene/level. This method of loading different levels has been basically instantaneous. (For context, the scenes each contain 1 room, similar in size to Curse of the Dead Gods, image below).



    I have now written a basic procedural generation script that builds the kinds of levels I need on loading the scene, but it takes a little bit of time to generate all the content before its ready to go. Currently this is only about 0.7s on average, but considering how bare bones my levels currently are, this seems like a problem that will scale drastically, and I should start thinking about it sooner rather than later.

    Some of this time can doubtless be cut down by making my procedural generation code more efficient, and some can be "hidden" by a small fade-out-in transition between scenes, but I'm wondering what are some other potential improvements I could make? Is it possible to, for example:

    1. Start loading the next scene while still in the current scene and store that away somehow until it is called?
    2. Generate the next room within the same scene, but make it a "low priority process", so that it only gets resources if the rest of the game is running smoothly?

    These may be silly solutions, but they were the first to come to mind. I feel certain there has to be some smart way of tackling this, but I'm not even sure what I should be googling if I'm honest :D

    Is there some kind of "industry standard" way of doing things I'm just not aware of yet, or at least a name for the process? Can anyone point me in the direction of related resources?

    Thanks for taking the time to read!
     
    Last edited: Dec 2, 2021
  2. Ne0mega

    Ne0mega

    Joined:
    Feb 18, 2018
    Posts:
    745
    Both your solutions are complicated, adding complications and problems and perhaps even slowdowns for a problem you are not even sure you are going to have. I say this as somebody who has worked on a complex procedurally generated game for years now... do not optimize until you have to, because you think you know what will cause problems, but really you don't, and often your solutions will cause problems worse than the original problem, that in reality, never manifests.
     
    Cuddles_ likes this.
  3. exp626stitch

    exp626stitch

    Joined:
    Mar 31, 2020
    Posts:
    14
    I have two solutions that might work, but don't take my word for it.

    1. Object Pooling. This will let you spawn in tons of GameObjects quickly without much lag or performance issues.

    2. In combination with Object Pooling, you could have each room and hallway have a script that stores a var of a custom class type:
    Code (CSharp):
    1. public GamePos myGamePos;
    Code (CSharp):
    1. public class GamePos : MonoBehaviour
    2. {
    3.     Vector3 cornerOne;
    4.  
    5.     public Vector3 CornerOne
    6.     {
    7.         get { return cornerOne; }
    8.         set { cornerOne = value; }
    9.     }
    10.  
    11.     Vector3 cornerTwo;
    12.  
    13.     public Vector3 CornerTwo
    14.     {
    15.         get { return cornerTwo; }
    16.         set { cornerTwo = value; }
    17.     }
    18.  
    19.     public GamePos (Vector3 cornerOne, Vector3 cornerTwo)
    20.     {
    21.         this.cornerOne = cornerOne;
    22.         this.cornerTwo = cornerTwo;
    23.     }
    24.  
    25.     public void SetNewGamePos(Vector3 cornerOne, Vector3 cornerTwo)
    26.     {
    27.         this.cornerOne = cornerOne;
    28.         this.cornerTwo = cornerTwo;
    29.     }
    30. }
    Then, in your GameManager script, you can have an array of that script like this:
    Code (CSharp):
    1. public List<List<ScriptThatStoresPositionClass>> dataZ = new List<List<ScriptThatStoresPositionClass>>();
    2. public List<List<ScriptThatStoresPositionClass>> dataX = new List<List<ScriptThatStoresPositionClass>>();
    3.  
    This is a jagged list, which basically is like this: List<ListOf_i_Through_i_PlusTen<ScriptThatStoresPositionClass>>, so when you want to add a another 10 x/z's, do
    Code (CSharp):
    1. dataZ.Add(new List<ScriptThatStoresPositionClass>())
    And then fill that list with any object that is in that group of x/z's
    Code (CSharp):
    1. dataZ[1].Add(object);
    Then use some fancy if and elses and get a group of objects that should spawn near the player and spawn them if they don't exist, or turn them on if they do, and if they are too far away from a certain distance, destroy them (make sure to save their data first). Sorry I cant write code for this part, my mind is too tired.
     
    Cuddles_ likes this.
  4. exp626stitch

    exp626stitch

    Joined:
    Mar 31, 2020
    Posts:
    14
    @Cuddles_ I realized that for my second solution, there is an easier solution, I found this video that shows something that you can adapt for your own code:
     
    Cuddles_ likes this.