0

Here is the code of my scriptable object:

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

namespace ModelManager
{
    [CreateAssetMenu(fileName = "New Texture Set", menuName = "Model Manager/New Texture Set")]

    public class TextureSetSO :  ScriptableObject
    {
        [SerializeField]
        public RaceModelSO race;
        public List<Textures> textures;
        private RaceModelSO _race;

        private void OnEnable()
        {
            _race = race;
        }

        private void OnValidate()
        {
            if (race != _race)
            {
                _race = race;
                textures.Clear();
                if (race)
                {
                    if (race.GetRaceBodySlots().Length != 0)
                    {
                        for (int i = 0; i < race.GetRaceBodySlots().Length; i++)
                        {
                            Textures textures = new Textures();
                            textures.raceSlot = race.GetRaceBodySlots()[i];
                            this.textures.Add(textures);
                        }
                    }
                }
            }
            EditorUtility.SetDirty(this);
            AssetDatabase.SaveAssets();
        }

        private void OnDestroy()
        {
            AssetDatabase.SaveAssets();
        }

        private void OnDisable()
        {
            AssetDatabase.SaveAssets();
        }
    }
    [Serializable]
    public class Textures
    {
        public RaceSlotSO raceSlot;
        public Texture normalMap;
        public Texture albedoMap;
        public Texture metalicMap;
        public Texture ambientOcullsionMap;
        public Texture emissionMap;
    }
}

Whenever I use the editor to set anything inside the List<Textures> textures and then if I close Unity everything is getting lost.

Why is that? How can I keep the changes when close and open back Unity? Any way to store that info to the disk ?

2
  • in case it helps, when I use scriptable objects, I do not do all the OnEnable , OnDestroy, OnDisable, OnValidate...stuff I see in your script. Just inheriting from scriptable object, generation the instance from the menu option ([CreateAssetMenu...) and the dragging my fields to the [Serializable] classes exposed fields is enough. I suggest you might be overwritting your references in some of that logic in case its needed Commented Jul 29, 2021 at 14:13
  • @rustyBucketBay thanks for the comment. How is that related to the problem of not saving the scriptable object ? Commented Jul 29, 2021 at 14:35

2 Answers 2

1

Problem

The reason why this happens is that the

private RaceModelSO _race;

is not serialized => Not saved.

Thus, everytime you reopen the project _race = null and therefore the check

if (race != _race)

is true and you erase all textures.


Solution

If you need the other field _race to be serialized as well you will need to have [SerializeField] (btw it makes no sense on a public field)

[SerializeField] private RaceModelSO _race;

if you want to serialize it but not exposed in the Inspector you can use

[HideInInspector] private RaceModelSO _race;

you don't need [SerializeField] then, as it is already included in the [HideInInspector].


Note

You should not call AssetDatabase.SaveAssets() here at all. You do this by pressing CTRL + S.

Makes little sense to do this in OnDestroy or OnDisabled at all for a ScriptableObject and is also extremely expensive doing it for every OnValidate call!

Sign up to request clarification or add additional context in comments.

Comments

0

You need to call EditorUtility.SetDirty(scriptableObject). Although you seem to call it inside OnValidate, OnValidate isn't called when modifying variables from code. It is called only when modifying the variable via Inspector or undoing/redoing a prior change.

An alternative to EditorUtility.SetDirty is to call Undo.RecordObject(scriptableObject) prior to modifying the ScriptableObject; this method also allows undoing/redoing the change.

P.S. You don't need to call EditorUtility.SetDirty or AssetDatabase.SaveAssets inside OnValidate. You also don't need [SerializeField] attribute on a public field.

2 Comments

Whenever I use the editor to set anything doesn't sound like runtime changes or via code is OPs situation. The issue rather lies in what is serialized and what not, see my answer ;)
@derHugo You are right, I've misread the situation.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.