ScriptableSingleton can't save: "ArgumentException: Path cannot be the empty string or all whitespace."

I’m using the ScriptableSingleton for the first time (Unity - Scripting API: ScriptableSingleton<T0>)

I use it to create and store IDs for npcs and other stuff.

But when I use the Save() method, it throws the error: “ArgumentException: Path cannot be the empty string or all whitespace.”

What am I missing? I’m doing the same as in the example in the unity docs, there doesn’t seem to be a way to specify the path appart from using [FilePath()], which I do. So why do I get that error?

Full code:

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

[FilePath("IDs.foo", FilePathAttribute.Location.ProjectFolder)]
public class ID : ScriptableSingleton<ID>
{
    [SerializeField]
    private List<bool> TrainerIDs; //keeps track of which IDs are in use
    [SerializeField]
    private List<bool> NPCIDs; //keeps track of which IDs are in use

    private int GetID(ref List<bool> IDs)
    {
        if (IDs == null)
        {
            IDs = new List<bool>();
        }
        else
        {
            for (int i = 0; i < IDs.Count; i++)
            {
                if (!IDs[i])
                {
                    IDs[i] = true;
                    return i;
                }
            }
        }
        IDs.Add(true);
        Save(true);
        Debug.Log("MySingleton state: " + JsonUtility.ToJson(this, true));
        return IDs.Count - 1;
    }

    public int GetTrainerID()
    {
        return GetID(ref TrainerIDs);
    }

    public void RemoveTrainerID(int iD)
    {
        TrainerIDs[iD] = false;
        Save(true);
    }

    public int GetNPCID()
    {
        return GetID(ref NPCIDs);
    }

    public void RemoveNPCID(int iD)
    {
        NPCIDs[iD] = false;
        Save(true);
    }
}

Are you trying to use this in a build? ScriptableSingletons are an editor tool.
That might explain the empty path (though I’m not 100% it’s the reason).

In any case, your code won’t compile in a build, so it’s better to choose some other strategy.

If I replace FilePathAttribute.Location.ProjectFolder with FilePathAttribute.Location.PreferencesFolder in the FilePath, then it does work.

Does the ProjectFolder location simply not work for this for some reason?

I would prefer it to be saved in the project, cause it’s a file I only need in this project.

No, It’s for editor purposes, not for in a build.

1 Like

The implementation of ScriptableSingleton<T>.Save requires a path that has a parent directory (e.g. "SomeFolder/IDs.foo") on the FilePathAttribute (Path.GetDirectoryName returns an empty string when just a filename is passed). Prepending a folder to the path should fix this.

2 Likes

Ah yes, that seems to fix it.
Thanks!

I thought it would be relative to the project folder, so leaving out a subfolder would just place it at the root of the project.
But that doesn’t seem to be the case.

Where does it actually store this file? I can’t seem to find it anywhere.

If it’s in FilePathAttribute.Location.ProjectFolder, it’s relative to the root of the project, which is the folder that contains Assets and ProjectSettings.

Yeah, I just found it. The problem was that it seemingly didn’t exist anymore.
By which I mean that I used the scriptablesingleton yesterday. Today I reopen my project and I notice the scriptablesingleton has it’s data lost, so I look for the file and it’s nowhere to be found, but after saving the singleton again, I could find the file.
Meaning the file got deleted after closing unity for some reason?