Saving ScriptableObject Skill List

Announcements, support questions, and discussion for the Dialogue System.
Post Reply
User avatar
Tony Li
Posts: 22054
Joined: Thu Jul 18, 2013 1:27 pm

Saving ScriptableObject Skill List

Post by Tony Li »

Here's one way to to save a dynamic list of ScriptableObject assets in the Dialogue System.

Unity does not serialize ScriptableObject references. For example, say you have a ScriptableObject like this:

Code: Select all

public class Skill : ScriptableObject
{
    public string description;
}
And the player has a component that maintains a list of skills:

Code: Select all

public class PlayerSkills : MonoBehaviour
{
    public List<Skill> skills;
    public void LearnSkill(Skill newSkill) { skills.Add(newSkill); }
}[code]

Unity cannot serialize and deserialize the List<Skill>. One workaround is to use an additional ScriptableObject asset that references all Skill assets:
[code]public class SkillDatabase : ScriptableObjects
{
    public List<Skill> allSkills; //<-- ASSIGN ALL SKILL ASSETS.
}
To "save" skills, you can record which elements of PlayerSkills.skills are in the skill database and represent it in a string. To "restore" skills, you can reconstruct the skills list from the string. For example:

Code: Select all

public class PlayerSkills : MonoBehaviour
{
    public SkillDatabase skillDatabase; //<-- ASSIGN SKILL DATABASE ASSET.
    public List<Skill> skills;
    public void LearnSkill(Skill newSkill) { skills.Add(newSkill); }
    
    public string SaveSkillsToString()
    {
        var indices = new List<string>();
        foreach (var skill in skills)
        {
            indices.Add(skillDatabase.allSkills.IndexOf(skill));
        }
        return string.Join(",", indices);
        // You could save this string in a Saver component or use DialogueLua.SetActorField().
    }
    
    public void RestoreSkillsFromString(string s)
    {
        var indices = s.Split(',');
        skills.Clear();
        foreach (var index in indices)
        {
            var skill = skillDatabase.allSkills[SafeConvert.ToInt(index)];
            skills.Add(skill);
        }
    }
}
Post Reply