Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Question Coding tree structures

Discussion in 'Scripting' started by sigma-z-1980, Sep 27, 2023.

  1. sigma-z-1980

    sigma-z-1980

    Joined:
    Oct 27, 2015
    Posts:
    5
    For example, a tech tree in a 4X game or any sort of progress/skill tree. The immediate solution would be a dictionary of course, in its simplest form:

    Dictionary<string, List<string>> TechTree = new Dictionary<string, List<string>>();
    TechTree["Fire Bolt"]=new List<string>{"Fire Ball", "Fire Wall"};


    But, this, first of all, feels clunky, but, more importantly, doesn't factor in cases with multiple requirements. For example, adding a requirement

    TechTree["Chaos Mastery"]=new List<string>{"Firewall"};


    What if I need to extract the list of requirements for a tech, Firewall in this case?
     
  2. CodeSmile

    CodeSmile

    Joined:
    Apr 10, 2014
    Posts:
    3,899
    You wouldn't use strings for that but structs or classes.

    TechTree is a class. It allows to query any Tech - the type(s) of collections used are internal details that aren't exposed.

    Tech is a class. It has a name, a cost, a status (locked, in progress, researched) and a list of requirements (other Tech whose status must be "researched").
     
  3. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,563
    YES... yes... this ^ ^ ^ ^ for sure. And take it a step further and learn about ScriptableObjects. ScriptableObjects are absolutely MADE for tech trees and other predefined data. It's insane... check it out:

    ScriptableObject usage in RPGs:

    https://forum.unity.com/threads/scr...tiple-units-in-your-team.925409/#post-6055289

    https://forum.unity.com/threads/cre...ssigned-in-the-inspector.946240/#post-6174205

    Usage as a shared common data container:

     
  4. sigma-z-1980

    sigma-z-1980

    Joined:
    Oct 27, 2015
    Posts:
    5
    In case I don't want to create a class, is it possible to get by with enum?
     
  5. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,563
    Enums are just integers known by another name, nothing more.

    They are also not a good idea to use in Unity. Again, ScriptableObjects are WAY more robust.

    Here's the skinny:

    Enums enums are bad in Unity3D if you intend them to be serialized:

    https://forum.unity.com/threads/bes...if-not-do-something-else.972093/#post-6323361

    https://forum.unity.com/threads/unity-card-game-structure.1006826/#post-6529526

    It is much better to use ScriptableObjects for many enumerative uses. You can even define additional associated data with each one of them, and drag them into other parts of your game (scenes, prefabs, other ScriptableObjects) however you like. References remain rock solid even if you rename them, reorder them, reorganize them, etc. They are always connected via the meta file GUID.

    Collections / groups of ScriptableObjects can also be loaded en-masse with calls such as
    Resources.LoadAll<T>().


    Best of all, Unity already gives you a built-in filterable picker when you click on the little target dot to the right side of a field of any given type... bonus!
     
  6. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    5,769
    You're not going to be able to make a tree-like data structure, or any kind of structure without encapsulating the data in classes and structs.

    Don't be afraid to create new classes.
     
    Nad_B likes this.
  7. Nad_B

    Nad_B

    Joined:
    Aug 1, 2021
    Posts:
    303
    Here is my Research (Tech tree) item:

    Code (CSharp):
    1. public class ResearchItem : BindableObject
    2. {
    3.     private ResearchState _state;
    4.  
    5.     public ResearchItem([NotNull] ResearchDataScriptableObject data, [NotNull] ResearchItem parent, [NotNull] IReadOnlyList<ResearchItem> children, ResearchState state)
    6.     {
    7.         Data = data ? data : throw new ArgumentNullException(nameof(data));
    8.         Parent = parent ?? throw new ArgumentNullException(nameof(parent));
    9.         Children = children ?? throw new ArgumentNullException(nameof(children));
    10.         Id = data.UniqueId;
    11.         State = state;
    12.     }
    13.  
    14.     public Guid Id { get; }
    15.  
    16.     // SO containing necessary info (points to unlock, effects...)
    17.     [NotNull]
    18.     public ResearchDataScriptableObject Data { get; }
    19.  
    20.     [CanBeNull]
    21.     public ResearchItem Parent { get; }
    22.  
    23.     [NotNull]
    24.     public IReadOnlyList<ResearchItem> Children { get; }
    25.  
    26.     // State is an Enum: Locked, Unlocked, Acquired
    27.     public ResearchState State
    28.     {
    29.         get => _state;
    30.         set => Set(ref _state, value);
    31.     }
    32. }
    Each item has a reference to its parent (if root item, it's null) and its children. You can easily construct a graph of nodes from a list of this to display in UI. To design the tree visually, I use the excellent xNode. A lot better, faster and easier to visualize than assigning relationships manually in the Editor.

    Editor:
    upload_2023-9-28_0-30-22.png

    In game UI (generated automatically)
    upload_2023-9-28_0-31-21.png
     
    Last edited: Oct 3, 2023
    spiney199 likes this.
  8. sigma-z-1980

    sigma-z-1980

    Joined:
    Oct 27, 2015
    Posts:
    5
    That's pretty cool, thanks. Does the tree in the last image appear only in development, or it can be integrated in the actual game for the players to see?
     
  9. Nad_B

    Nad_B

    Joined:
    Aug 1, 2021
    Posts:
    303
    The last image is actually from the game (runtime), and it's all generated automatically from the research tree I construct during runtime (start of the game). The image before that is from the Editor (using xNode).
     
    sigma-z-1980 likes this.