简体   繁体   中英

C#/Unity - Unable to save scriptable object to disk

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 ?

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!

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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM