Search Unity

Concept: Mindmap like skill tree auto generation

Discussion in 'Scripting' started by Gegenton, Nov 15, 2019.

  1. Gegenton

    Gegenton

    Joined:
    Nov 4, 2019
    Posts:
    9
    Dear forum,

    I was looking for similar approaches for quite some time now, but can't find much useful reference.

    I try to program something like a mindmap, that looks like a classic Diablo 2 skill tree. This skill tree shall be generated automatically on run time, because there will be A LOT of "skills" (it's a tech tree actually) visualized by cards to be placed in the tree. Also by A LOT I mean that they might change over time, depending on me adding additional techs etc. in addons or whatnot.

    Anyhow this is my current approach (caution, no real code):

    Code (CSharp):
    1. class MapCreator {
    2. int Grid[,]          // the cards will be placed on a grid
    3. int AllCards[]    // stores all unique card IDs
    4. int clm              // stores the current(?) column information
    5. int row             // stores the current(?) row information
    6.  
    7. scriptableObject card {
    8. int cID[]             // each cards unique ID, row, column (row and column will be determined on runtime)
    9. int parentID[]    // one (or more) parent IDs, referencing the unique ID of cID[]
    10. int childID[]       // one or more childen IDs, referencing the unique ID of cID[]
    11. }
    12.  
    13. /*
    14. Rules
    15. 1) A child will always be created to the right of the previous one if it is dividable by 2, otherwise to the left of the previous one
    16. 2) A card always has an empty space to its right
    17.  
    18. ______x_____
    19. ______|_____
    20. ____x_x_x___
    21. ________|___
    22. ________x_x_
    23. */
    24.  
    25. void switch CreateChildren {
    26. // defined cases based on the number of children to make things easier (max. 5 children);
    27. // foreach, if etc. would be sexier
    28. case x {  // 0 = no children, 1 = 1 child, 2 = 2 children etc.
    29. position[] = [clm, row]     // much complexer based on case and based on rules
    30. CheckPosition();
    31. PositionOkay:
    32.    CreateNode();     // save position in the grid in cID[]
    33.    CreateConnector();     // creates the connecting wire, I have an idea about this already
    34. }
    35. ...
    36. }
    37.  
    38. CheckPosition:
    39. void CheckPosition() {
    40. Check if recently added node already exists {
    41.     if no goto: PositionOkay;
    42.     else goto: PositionNOkay;
    43. }
    44.  
    45.  
    46. PositionNOkay:
    47. void MoveParent() {
    48. find already existing nodes parent;
    49. find position of current node in current nodes parent childenID[];
    50. if this position %2 = 0 {   // move it to the right of the was added to the right in the first place
    51. parent.clm+2;
    52. goto CreateChildren;
    53. }  
    54. else {            // otherwise move it to the left
    55. parent.clm-2;
    56. goto CreateChildren;
    57. }  
    58. }
    59. }
    60.  

    Obviously this is very messy, I have no access to a developer right now.

    I don't need a fully fleshed out solution for this, just wanted to ask if this is the right path to go or if there are other wonders of scripting that I have not thought about before. Especially I'm not sure if this process is looping correctly. Can I even start it or to I need to have it run in update?
    By the way: the initialisation and visualisation will be seperated most probably. I "only" need the tree to develop itself.

    Basically the tree should generate itself based on all existing scriptableObjects (the first one will be set to start the process) AND the nodes need to be referencable later on (I hope this works already by giving them a unique ID (that is also the same as the cards unique ID) so that I can simply match them later).

    Hope this was not too messy, but again, it's really more about the concept right now.


    Thanks a ton and kind regards from Germany,

    Marcel
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,747
    It certainly seems like a reasonable path.

    If you are just constructing links between stuff in the tree, do it once and Start() is as good a place as any.

    I would NOT do this approach. Use the actual name of the ScriptableObject on the disk as the unique identifier. This means you must be sure you don't have two of them named the same, but trying to keep yet another unique identifier straight will a) provide virtually no value, and b) lead to lots of potential bugs. Just use the .name field as your unique primary key.
     
  3. Gegenton

    Gegenton

    Joined:
    Nov 4, 2019
    Posts:
    9
    Thanks Kurt,

    Read your answer earlier but didn't have a chance for a reply yet.

    Keeping this thread updated on the progress (if there is one :p).


    KR

    Marcel
     
  4. Gegenton

    Gegenton

    Joined:
    Nov 4, 2019
    Posts:
    9
    Hi again,

    I came to the conclusion that the graphical interpretation of the tree would be a coding nightmare. The way that I intend to have multiple dependencies between different nodes (not only the ones that are direct children to their parents, but also ones that simply influence a node or even a group of nodes from some other "place" on the map) would end up in a positioning horror. Therefore I plan the tree ahead, place the prefebs manually using snap to grid in editor and hope that I don't have to redo it ten times :O

    Anyway calculating the different effect of (activated) nodes is still a must of course. The player needs to get his bonuses from the tech tree. Due to above mentioned complexity I came up with the following solution:

    upload_2019-11-25_15-52-40.png

    Each blue triplet of quads stands for a node. There is an operator (left quad) and to temporary operators for this operator (right quads).

    I hope there's no further explenation needed. If you have questions (or think this is plain stupid and won't work) - let me know ;) Will keep this thread updated as promised. Implementation will be postponed to a later date though, need to have the test environment set up first.


    KR

    Marcel