Home > database >  How to build a pre-determined array of objects in C#?
How to build a pre-determined array of objects in C#?

Time:11-23

To preface this question, I'm a hobby programmer that's been learning on/off for the past 7 years, and mostly dabbled with Node.JS in several different settings and projects. I now decided to take the leap to another major language and picked up C# to start learning game development and the likes. I am in the process of building a skill tree and I can't really understand how to store the information I need for each skill in a clean and orderly fashion without a bunch of empty GameObjects (Unity) holding that info.

I know (at least my favorite way of) how to do this in Node.JS, but I can't find the right information on converting this to C#.

Node.JS example

var skillTree = [
   {
      name: "Skill1",
      effect: skill1Func,
      unlocked: true,
      prereqs: [ ]
   },
   {
      name: "Skill2",
      effect: skill2Func,
      unlocked: false,
      prereqs: [1, 5]
   }
];

As you can see, it's just an array of objects, all following the same properties, but the properties are pre-determined instead of added. I just can't find the right path to go to store this information for use in C#, so if anyone could help me out, that would be appreciated!

CodePudding user response:

This answer basically has it all.

I anyway wanted to add a Unity specific suggestion / extension:

Instead of "hard coding" this in a script at all and using index based int[] PreReqs wouldn't it be more dynamic and extendable to simply create and configure skills in the Unity editor?

I would therefore use ScriptableObject which basically allows you to create skill assets which live in the Assets and are not attached to a specific GameObject.

[CreateAssetMenu]
public class Skill : ScriptableObject
{
    [SerializeField] private SkillEffect effect;
    [SerializeField] private Skill[] preReqs;

    public string Name => name;
    public SkillEffect Effect => effect;
    public bool Unlocked;
    public Skill[] PreReqs => preReqs;
}

Then you would create instances of this via Assets -> Right click -> Create -> Skill, name and configure it. This way you an easily directly link them among each other in the preReqs and don't have to rely on any indices.

In your final consumer component you would finally reference them all in a field

public Skill[] skillTree;

And another extension of this - depending on your needs for the Effect: If Effect is not e.g. an enum but rather a custom method you could simply make this Skill an abstract type and have different child skills based on it like e.g

public abstract class Skill : ScriptableObject
{
    [SerializeField] private Skill[] preReqs;

    public string Name => name;
    public abstract void Effect();
    public bool Unlocked;
    public Skill[] PreReqs => preReqs;
}

and then e.g.

[CreateAssetMenu]
public class SayHelloSkill : Skill 
{
    public override void Effect()
    {
        Debug.Log("Hello World!");
    }
}

you can pass whatever parameters you need to the method and basically execute any code on them while you create instances of each skill and reference them in the skillTree as before. I personally call this "Scriptable Behavior" and though it is slightly abusing the idea of ScriptableObject I find it quite powerful

CodePudding user response:

Typically you would create a class object to define the structure of the data. Then you can create a variable of the type of that class and populate the data in the constructor. Example:

public class skillItem {
    public string Name { get; set; }
    public SkillEffect Effect { get; set; }
    public bool Unlocked { get; set; }
    public int[] PreReqs { get; set; }
}

public skillItem[] skillTree = new skillItem[] {
    {
        Name = "skill1",
        Effect = skill1Func,
        Unlocked = false,
        PreReqs = new int[] { 1, 5 }
    },
    {
        Name = "skill2",
        Effect = skill2Func,
        Unlocked = false,
        PreReqs = new int[] { 20, 30 }
    }
}
  • Related