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.