- Home /
How do I have an EditorWindow save it's data inbetween opening and closing Unity? C#
I am trying to make an EditorWindow that will store global data about my application, data which I want every level to be able to access. So my first route of going about this was to just make a static public class GlobalData. In it is all the data I want to store. Then in my EditorWindow I do a simple GlobalData.whatever this works in between opening and closing the EditorWindow. But not inbetween opening and closing Unity. It seems to not save changes to the variables in my static class. I do have [System.Serializable] put about my static class, and I have even tried calling SetDirty on my GlobalData data, but that doesn't work.
From the advices of someone else I tried to create GlobalData NOT as a static, but rather just public. Then I create an Instance of GlobalData in my EditorWindow Class. But this does not save the data between opens and closes of even just the EditorWindow! I assume of course because the instance of GlobalData is being made in the EditorWindow so it loses that instance when it is closed.
I've tried messing around with making my GlobalData class a ScriptableObject, but that doesn't work.
I've seriously spent like the past 18 hours sitting here trying any and everything I can think of and am running out of ideas :( Please Help. If anyone could just give me the most base simple example code for an EditorWindow that somehow saves it's data between open and closes of Unity, I would be so grateful. I cannot find any example projects anywhere that show how to do this.
And here is the code I've made thus far:
using UnityEngine;
using UnityEditor;
public class PanoSetup : EditorWindow
{
[MenuItem ("Window/PanoSetup")]
static void Init () {
//PanoSetup window =
EditorWindow.GetWindow (typeof (PanoSetup));
}
void OnGUI () {
GlobalData.texture = (Texture2D) EditorGUILayout.ObjectField(
"Find Dependency",
GlobalData.texture,
typeof(Texture2D));
}
}
using System.Collections;
using UnityEngine;
[System.Serializable]
static public class GlobalData {
static public string texturePath = "temp";
static public int what = 1;
static public Texture2D texture = null;
}
It's a pity Unity doesn't automatically save an asset holding the serialized properties of an EditorWindow.
Answer by ThomLaurent · Apr 02, 2018 at 02:06 AM
You could use Unity's serialization combined with JsonUtility and EditorPrefs to save your fields and then load them up in just 4 lines :
public class AnExampleWindow : EditorWindow
{
[SerializeField] private Vector2 _someV2Field = Vector2.zero;
[SerializeField] private Color _aBitOfColor = Color.green;
[SerializeField] private List<Color> _aFlagColors = new List<Color> { Color.blue, Color.white, Color.red };
[SerializeField] private bool _amIFrench = true;
[SerializeField] private string _savePath = "Assets/Resources/anFlag.png";
private string _aNotSerializedString;
private int _aNotSerializedInt;
protected void OnEnable ()
{
// Here we retrieve the data if it exists or we save the default field initialisers we set above
var data = EditorPrefs.GetString("AnExampleWindow", JsonUtility.ToJson(this, false));
// Then we apply them to this window
JsonUtility.FromJsonOverwrite(data, this);
}
protected void OnDisable ()
{
// We get the Json data
var data = JsonUtility.ToJson(this, false);
// And we save it
EditorPrefs.SetString("AnExampleWindow", data);
// Et voilà !
}
// Your pretty code here...
}
Answer by Diet-Chugg · Apr 17, 2015 at 06:04 PM
There are several ways to do this. I would create a/several ScritpableObject and store them in your project's Resources folder.
I'd make a class:
public class MyScriptableObjectClass : ScriptableObject
{
//Savable data here
}
Than I would save and load it using:
MyScriptableObjectClass myInstance = (MyScriptableObjectClass )Resources.Load("myInstance.asset") as MyScriptableObjectClass;
if(myInstance == null)
{
myInstance = CreateInstance<MyScriptableObjectClass>();
AssetDatabase.CreateAsset(myInstance , "Assets/Resources/myInstance.asset");
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
In The Game you could load the class from anywhere using MyScriptableObjectClass myInstance = (MyScriptableObjectClass )Resources.Load("myInstance.asset") as MyScriptableObjectClass; and access the data there.
(Edit: Quick Note: The code I wrote is not tested code. I don't know if it will work if you just copy paste it. But it will point you to the right classes to use.)
This is quite an old question, but it's the first one that comes up when doing a google search. Scriptable objects are a better solution that editor prefs for 3 reasons.
They can be shared between machines, projects and can be packaged.
They're easier to debug because you can see the saved data in the inspector.
Unity seems to do this and seems to be their standard. For example lighting data and navigational data are both stored as assets.
Answer by Jake-L · May 22, 2011 at 06:35 AM
Use EditorPrefs to save and load values. Load them in OnEnable and write them in OnDisable and you're done.
Right, the best way. Or maybe use static variables but it just "saves" the values until Unity is closed. EditorPrefs saves it actually on disk ;)
I wanted to use statics like that...
I noticed something new, if you make a ScriptableObject Class, or a class that extends nothing. When you click on that script inside of the project pane, you can see the public properties like Texture2D in the inspector! So clearly such a class is capable of storing data input to it form external sources while only being in the project pane. I however could not figure out how to get at this data. Object.FindObjectOfType will succesfully find a ScriptableObject in the project pane and load it, and get data from it, but I could not put data back into it.
Have you read my answer? AssetDatabase.CreateAsset will do what you want (i guess :D). You have to store your object as ".asset"
@fseydel:
Thanks for pointing out that broken link. I've fixed it in the answer.
Answer by Bunny83 · May 22, 2011 at 10:40 AM
Well, i just saw that you want to store complex types (like texture references). Well another way would be to create a separate script that saves your variables to your assets. Just create a GameObject (set the hideflags) and attach your script to it (all done from within your editor-script). Use AssetDatabase and EditorUtility to save and load it as prefab.
Well, i guess a class that is derived from ScriptableObject should also be possible to save as asset.
Answer by Veehmot · Jun 02, 2013 at 09:13 PM
This blog post tells you all about serializing objects for Editor scripts.
That example doesn't work for me. The moment I close the window everything is lost. Any idea where I can find an example that works?
This example is a mess. It does not provide a solution, it only shows the trouble of this try
Your answer
Follow this Question
Related Questions
Prevent changes in ScriptableObject type Asset in Editor. Dont save it. 0 Answers
Multiple Cars not working 1 Answer
EditorWindow properties in Game Code 1 Answer
Distribute terrain in zones 3 Answers
When is a static game object static? 1 Answer