Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice
  3. Dismiss Notice

Resolved Question about using a Dictionary that includes another Dictionary

Discussion in 'Scripting' started by iimuli, May 23, 2024.

  1. iimuli

    iimuli

    Joined:
    Apr 21, 2022
    Posts:
    19
    Hey!
    I'm currently creating a small tabletop prototype. I'm trying to set up ground pieces on the board and setting them in some kind of data container. It currently has X-amount of (grey) main planes that are setup in order on rows and each plane is covered by (black) side planes. There are special corridors with functionality that are different colors. I got base codes for instantiating stuff on pools and then activating and setting their positions accordingly depending on player settings

    Sieppaa.PNG



    When I create a new game I want to store each side planes row (int 0,1,2,3....), left/right side (bool isRight) and if is occupied (bool occupied). So later I can check if that spot has a corridor, and forexample I can set the special corridor Zpos +-10 depending on side so that it doesnt overlap with the black corridor. I'm having trouble figuring out the best approach for this. What I'm currently testing is dictionary on this format:

    Code (CSharp):
    1.  static Dictionary<int, Dictionary<bool, bool>> corridor = new Dictionary<int, Dictionary<bool, bool>>();
    2.  
    3.     public static void AssignCorridor(int row, bool isRight)
    4.     {
    5.          //(Check if spot is unoccupied)
    6.          //Assign/Add to corridor int(row) and side (isRight true or false) as occupied (true)
    7.     }
    8.     public static bool CheckRow(int row, bool isRight)
    9.     {
    10.         //Check corridor at int(row) and side (isRight true or false) and return if is occupied(true/false)
    11.     }
    12.     public static void RemoveCorridor(int row, bool isRight)
    13.     {
    14.          //(Check if spot is occupied)
    15.          //Remove corridor at int(row) and side (isRight true or false) and set as unoccupied (false)
    16.     }
    After googling and testing I can't seem to figure out how to use this kind of dictionary within dictionary. I've been trying some workaround with Vector3[] arrays or adding all Corridor scripts to List/array and checking every one for the rows and side bools but I find those pretty unintuitive.

    Question:

    How would I use this kind of a dictionary and could I get some examples for each function? (assign, check and remove)

    It's also very much possible that my approach is a disaster, so If anyone has any better ways of doing this and preferably with examples I'm all ears!
     
    Last edited: May 23, 2024
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    39,357
    It feels like you might need some kind of layered approach to your data.

    For instance, the grid of planes might be just a 2D array of some kind that defines what type or color each one is.

    Always better to go with some opaque logical thing like "grass" instead of "green," so you can change the presentation later, such as if you decide you want purple grass. :)

    Adjacent to that you would have corridors, described perhaps in terms of the coordinate space of the planes.

    Like if you're talking the Chutes and Ladders game, it would be a grid of 10x10 of cells, along with a list of connections that referred to these cells. The connections would be either ladders (up) or chutes/snakes (down).

    But wrapping your stuff up in a clear API (like you're doing above) is definitely the way to go, and it also lets you think about "what do I want to do against this data," such as ask "can I go from here to there?" or "what is the path from point A to point B, perhaps passing through point C."
     
    lordofduct likes this.
  3. CodeSmile

    CodeSmile

    Joined:
    Apr 10, 2014
    Posts:
    6,922
    The inner dictionary can only have two keys: true and false, each of which can have a value of either true or false. That doesn't seem to make a whole lot of sense. ;)

    If you only need those two bool keys, use a Dictionary<int, bool[]> instead. Then simply assume that the bool array's index 0 is the false "key" and index 1 is the true "key".
     
    lordofduct likes this.
  4. iimuli

    iimuli

    Joined:
    Apr 21, 2022
    Posts:
    19
    Thank you for the responses!

    I managed to find out how to use the Dictionary, I got my plane placement working with this code + other checkers:

    Code (CSharp):
    1.  static Dictionary<int, Dictionary<bool, bool>> corridor = new Dictionary<int, Dictionary<bool, bool>>();
    2.  
    3.     public static void InitializeCorridors(int maxCorridors)
    4.     {
    5.         for(int i = 0; i < maxCorridors; i++)
    6.         {
    7.             corridor[i] = new Dictionary<bool, bool>();
    8.             corridor[i][true] = false;
    9.             corridor[i][false] = false;
    10.         }
    11.     }
    12.  
    13.     public static void AssignCorridor(int row, bool isRight)
    14.     {
    15.         if (corridor[row] != null)
    16.         {
    17.             corridor[row][isRight] = true;
    18.         }
    19.     }
    20.  
    21.     public static bool CheckRow(int row, bool isRight)
    22.     {
    23.         bool value = corridor[row][isRight];
    24.         return value;
    25.     }
    26.  
    27.     public static void RemoveCorridor(int row, bool isRight)
    28.     {
    29.         if (corridor[row] != null)
    30.         {
    31.             corridor[row][isRight] = false;
    32.         }
    33.     }
    34.  

    I'm not sure if there is a better way to do this but atleast its working :D Sieppaa.PNG Sieppaa2.PNG
     
  5. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,594
    Dictionaries of Dictionaries can get real confusing and unreadable real fast. Collections of collections in general can get real confusing real fast. Personally I try to avoid them because to make the code maintainable in any manner you have to document verbosely what exactly is going on here with the strange layout that instead you could have just.... created a simple data structure that better self-documents the intent (named fields help with that).

    You have a grid of tiles.

    Create a struct/class for your tile itself with any data needed about it (state, if it's occupied, etc):
    Code (csharp):
    1. //better define these, I'm just throwing what I see visually in your image here
    2. public enum TileType
    3. {
    4.     Grey = 0,
    5.     Black = 1,
    6.     Green = 2,
    7. }
    8.  
    9. public class Tile
    10. {
    11.     public TileType type;
    12.     public bool isOccupied;
    13. }
    Then yeah, you can throw these into a 2d array that represents the grid. If you want to get a tile adjacent to a given tile you step over 1 index in that direction. Done.
     
    Ryiah and Kurt-Dekker like this.
  6. iimuli

    iimuli

    Joined:
    Apr 21, 2022
    Posts:
    19

    I see! I'll make sure to test this out too just for the simplicity, still learning new stuff. Thank you!