How to store references between scriptableobject assets

I have a scriptableobject. I would like it to be able to contain a reference to another scriptableobject within it, and for this reference to be stored throughout development. Currently, the reference is being stored during an editor session, but as soon as I close and re-open unity, the reference has disappeared.

Is it not possible to serialise references to other scriptableobjects? And if it is not, is there a way that I can go about achieving the desired connection?

Here’s the basic outline of the code:

[System.Serializable]
public class DialogueElement : ScriptableObject
{
[Serializefield]
public DialogueElement outputDialogue;
}

So, in the Unity inspector, when I create the reference between two instances of this ScriptableObject by dragging and dropping, how is that reference created? Is there some sort of ID created in the background of Unity for each ScriptableObject?

I ask because this because of my current link of thinking:

In my custom dialogue editor window, the DialogueElements are stored in a list:

    private static List<DialogueElement> dialogues = new List<DialogueElement>();

Here’s a method in that editor for creating a new instance of the DialogueElement (Ignore the random number bit, it’s just to create a unique file name for now):

    private static void CreateDialogue()
    {
        DialogueElement dialogueElement = DialogueElement.CreateInstance(new Rect(correctedMousePos.x, correctedMousePos.y, DialogueElement.minWidth, DialogueElement.minHeight));

        //TODO - Come up with a naming convention
        var randNum = Random.Range(0f, 100f);
        string saveFilePath = dialogueAssetPath + sceneNameText + "/" + randNum + ".asset";

        AssetDatabase.CreateAsset(dialogueElement, saveFilePath);
        AssetDatabase.SaveAssets();

        DialogueElement newAsset = AssetDatabase.LoadAssetAtPath<DialogueElement>(saveFilePath);
        dialogues.Add(newAsset);
        EditorUtility.SetDirty(window);
    }

And then I have a button to call the following method to save the dialogues when I’ve made changes:

    private void SaveSceneDialogues()
    {
        UpdateSceneName();

        for (int i = 0; i < dialogues.Count; i++)
        {
            if (dialogues *!= null)*

{
//Create an asset from the current dialogue
if (!AssetDatabase.Contains(dialogues*))*
AssetDatabase.CreateAsset(dialogues_, dialogueAssetPath + sceneNameText + “/” + dialogues*.windowTitle + “.asset”);
else_

_AssetDatabase.RenameAsset(dialogueAssetPath + sceneNameText + “/” + dialogues.windowTitle + “.asset”,_
_dialogues.windowTitle);
}
}*_

AssetDatabase.SaveAssets();
EditorUtility.SetDirty(window);
}
The connections are created with this method that is in the DialogueElement class when an certain event is called from the custom editor window:
public void SetOutputDialogue(DialogueElement outputDialogue, Vector2 clickPos)
{
if (outputDialogue.windowRect.Contains(clickPos))
{
this.outputDialogue = outputDialogue;
}
}

My current thinking is that these references might not be being serialized between Unity sessions because the links are created between the DialogueElements that are in the dialogues list, and not between the actual asset files that are created, even though the links do appear in the asset files that are created, they just disappear between Unity sessions.
That might be nonsense though, but I’m struggling to find information on this.
I’m including the two classes so that anyone awesome enough to help out can try the editor and see it for themselves. If you include the two scripts in a project, you should be able to recreate the issue, providing that you create the following filepath:
Assets/Resources/Dialogue[76848-files.zip|76848]
Thanks in advance for any help!
Matt

In my custom dialogue editor window, the DialogueElements are stored in a list:

 private static List dialogues = new List();

Ah, I think we were assuming this data was in a monobehvior object somewhere, and thus automatically serialized to disk. A private Editor class member is NOT going to be saved to disk.

For this situation, you may want to take a look at: Unity - Scripting API: AssetDatabase.GUIDToAssetPath
and
Unity - Scripting API: AssetDatabase.AssetPathToGUID

These are useful for manually loading and saving particular assets. You’ll still need to store the list of GUID’s somewhere, I would think. I’m not quite clear on whats going on with the array initialization in your code, so cannot be more specific in my suggestion.

Yes I agree with @Glurth, The private static list is probably the problem, but I can’t confirm yet since I’m having errors of missing files with the files you provided. For now try making that one public and see what you get.

Edit: Okay so I was finally able to reproduce what was happening. Now for some reason using serialized objects and applying modified and updating doesn’t work, but something else worked. Setting the individual dialogues dirty seems to work.
You can loop over your dialogues each OnGUI(not really optimal) and make them dirty, or (best option) is wherever you draw the windows in your code, after each dialogue is drawn check if something on it was changed, if so make it dirty.

Another possiblity (which is also a good solution) is whenever you close the window/change scenes just loop over all the dialogues and make them dirty. This should hopefully fix your problems :slight_smile: