Unlocking Abilities

Edit: This is my current save set up, so in a build none of this will save at all or will it? I’m kind of a beginner with Scriptable Objects outside of what we were taught in the courses. You said read only so I’m guessing it means it won’t save the data correctly or at all. Is my set up redundant atm?

        [System.Serializable]
        struct SaveData
        {
            public List<bool> skillUnlocked;
            public List<int> cost;
            public List<int> skillID;
            public List<int> levelCap;
            public List<int> level;
            public int points;
        }

        public object CaptureState()
        {
            SaveData data = new SaveData();

            data.points = availablePoints;

            data.cost = new List<int>();
            data.skillID = new List<int>();
            data.level = new List<int>();
            data.levelCap = new List<int>();
            data.skillUnlocked = new List<bool>();
            
            for (int i = 0; i < skillsList.Count; i++)
            {
                data.cost.Add(skillsDictionary[i].RequiredPointsToUnlock);
                data.skillUnlocked.Add(skillsDictionary[i].Unlocked);
                data.skillID.Add(skillsDictionary[i].SkillID);
                data.level.Add(skillsDictionary[i].SkillLevel);
                data.levelCap.Add(skillsDictionary[i].SkillCap);
            }
            return data;
        }

        public void RestoreState(object state)
        {
            SaveData loadData = (SaveData)state;

            availablePoints = loadData.points;

            for (int i = 0; i < skillsList.Count; i++)
            {
                skillsDictionary[i].RequiredPointsToUnlock = loadData.cost[i];
                skillsDictionary[i].Unlocked = loadData.skillUnlocked[i];
                skillsDictionary[i].SkillID = loadData.skillID[i];
                skillsDictionary[i].SkillLevel = loadData.level[i];
                skillsDictionary[i].SkillCap = loadData.levelCap[i];
            }
        }

Ok, that might actually work since you’ll be adjusting the copy in RestoreState.

1 Like

After seeing this comment I isolated a scene and built it out and tested it… It does appear to work. But I’ll keep an eye on it down the track as I expand things for the skill tree! :slight_smile:

I made the changes I described above earlier about also checking for a level condition of any skill. It works well for me – I’m not afraid to be critiqued or to be shown a better method of doing all of this, so any student or brian feel free anytime.

Here’s what it looks like on a Skill now from the Editor Inspector. (Down the bottom I have 2 skills that are being checked as well as both skills requiring a certain level.)

I have a list of Skill Configs that each take in a skill and a level required. So in order to unlock this skill, it takes my “Ability 0” to be at level 2, whilst my “Ability 2” needs to have 3 points invested before it can be unlocked.

So inside the Skill script I made these changes:

        [Serializable]
        public class SkillConfig
        {
            public Skill dependency;
            [Range(0, 100)] public int skillLevelRequired;
        }
      
       // To have access to the skill dependencies as a list.
       [SerializeField] List<SkillConfig> skillConfig = new List<SkillConfig>();
       // Property to gain access inside SkillTree.
       public List<SkillConfig> SkillConfigs { get { return skillConfig; } set { skillConfig = value; } }

Once that was all done inside the Skill script I made an adjustment to how we iterate over our dependencies and used Linq to check “All” of the skill inside our skillConfig depenedencies and skill requirements to see whether they were satisfied to unlock the new skill.

Here’s the updated IsSkillUnlocked() method to handle this:

        bool IsSkillUnlocked(int id_skill)
        {
            // Creates a list of all skillConfigs Skill conditions for this particular inspectedSkill.
            var skills = skillsDictionary[id_skill].SkillConfigs.ToList();

            // If inspectedSkill has no dependencies or level requirements then we attempt to unlock the inspectedSkill immediately.
            if (skills.Count <= 0)
            {
                return UnlockSkill(id_skill);
            }

            // If inspectedSkill has dependencies, iterate over all found inside skills List.
            foreach (var skill in skills)
            {
                // If all SkillConfig prerequisites are met than proceed to unlock inspectedSkill.
                if (skills.All((skill) => skill.dependency.Unlocked && skill.dependency.SkillLevel >= skill.skillLevelRequired))
                {
                    return UnlockSkill(id_skill);
                }

                // Any or all of the dependencies were locked or the inspectedSkill dependency didn't exist.
                return false;
            }

            // If we didn't have enough points to spend or the inspectedSkill wasn't found.
            return false;
        }

I’m quite happy I am able to accomplish something like this.

Brian… you replied a lot and at times I felt that I was frustrating you so I apologize if I did. If I didn’t, thanks for sticking with me and lending me your thoughts on my whole process. This will be my last reply for now… any other students feel free to add more to this skill system if you wish and share it here!

I’m happy to help where I can. You’re definitely on the right track here! Well done!

1 Like

Privacy & Terms