Hey, I stuck with this for a good moment now, somewhere in my code, I have this :
if (!_instance.ContainsKey(T) || _instance[T] == null)
{
#if UNITY_EDITOR
_instance[T] = (DataHolder)ScriptableObject.CreateInstance(T);
Debug.Log(T.Name);
return null;
/*if (!Directory.Exists(Application.dataPath + "/DataHolders"))
Directory.CreateDirectory(Application.dataPath + "/DataHolders");*/
AssetDatabase.CreateAsset(_instance[T], "Assets/DataHolders/" + _instance[T].pathToBase + ".asset");
AssetDatabase.SaveAssets();
#else
t = LoadLast(T);
#endif
}
But it crash everytime on the ScriptableObject.CreateInstance(T).
T is a class extending DataHolder.
_instance is a Dictionary
pathToBase is a simple string.
I’ve already use this code with another class, and it worked, so i don’t understand. I used the debug class around those lines to see where it stuck, all work until this, and i don’t get why.
Any help would be very pleasant.
thanks, FireCube
EDIT : there’s the DataHolder class :
//Code written by Etienne Desrousseaux, alias FireCube, for the updater package.
//
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;
using System.IO;
using Crypting;
#if UNITY_EDITOR
using UnityEditor;
#endif
public class DataHolder : ScriptableObject
{
public static List<DataHolder> dataBases = new List<DataHolder>();
public const string pathToBases = "Data";
public string pathToBase
{
get
{
return GetType().ToString();
}
}
public static Dictionary<Type, DataHolder> _instance = new Dictionary<Type, DataHolder>();
public static T getInstance<T>() where T : DataHolder
{
T t = null;
if (_instance.ContainsKey(typeof(T)))
t = (T)_instance[typeof(T)];
if (t == null)
{
#if UNITY_EDITOR
t = CreateInstance<T>();
AssetDatabase.CreateAsset(t, "Assets/DataHolders/" + t.pathToBase + ".asset");
AssetDatabase.SaveAssets();
#else
t = LoadLast(typeof(T));
#endif
}
_instance[typeof(T)] = t;
return t;
}
public static DataHolder GetInstance(Type T)
{
if (!_instance.ContainsKey(T) || _instance[T] == null)
{
#if UNITY_EDITOR
_instance[T] = (DataHolder)ScriptableObject.CreateInstance(T);
Debug.Log(T.Name);
return null;
/*if (!Directory.Exists(Application.dataPath + "/DataHolders"))
Directory.CreateDirectory(Application.dataPath + "/DataHolders");*/
AssetDatabase.CreateAsset(_instance[T], "Assets/DataHolders/" + _instance[T].pathToBase + ".asset");
AssetDatabase.SaveAssets();
#else
t = LoadLast(T);
#endif
}
return _instance[T];
}
#if UNITY_EDITOR
public void open()
{
Selection.activeObject = this;
}
#endif
/// <summary>
/// Load the last data holder of this type that have already been downloaded
/// </summary>
/// <param name="T">the type, must extend DataHolder class</param>
/// <returns>the data holder loaded from last </returns>
public static DataHolder LoadLast(Type T)
{
DataHolder dh = null;
string path = Application.dataPath + "/" + pathToBases + "/" + ((DataHolder)CreateInstance(T)).pathToBase;
if (File.Exists(path))
{
AssetBundle ab = AssetBundle.LoadFromMemory(
File.ReadAllBytes(path)
.Decrypt(
SimpleConfig.getLine("pass", "UpdaterData")));
dh = (DataHolder)ab.LoadAsset(T.Name, T);
}
return dh;
}
/// <summary>
/// Download and save to disk a data holder, debug parameter exist for UNITY_EDITOR only
/// </summary>
/// <param name="T">the type for which we want to download the base</param>
/// <param name="onDone">the function to be executed when the download is finished</param>
/// <param name="onError">the function to be executed if an error happen durring the download, the saving to disk or when loading the base</param>
/// <param name="onUpdate">the function to be executed every <paramref name="updateRate"/>, sending the progress</param>
/// <param name="updateRate">the rate at which <paramref name="onUpdate"/> is called</param>
public static IEnumerable DownloadDataHolder(Type T, Action<DataHolder> onDone = null, Action<string> onError = null, Action<float> onUpdate = null, float updateRate = 0.05f
#if UNITY_EDITOR
, bool debug = false//reduce size on build
#endif
)
{
bool update = onUpdate != null;
string url = SimpleConfig.getLine("website", "UpdaterData") + "/" + T.Name + ".dat";
WWW www = new WWW(url);
#if UNITY_EDITOR
if (debug)
Debug.Log("Start downloading " + url + "
Corresponding Data Holder is " + T.FullName);
#endif
if (update)
{
while (!www.isDone)
{
yield return new WaitForSeconds(updateRate);
Action temp = onUpdate;
if (temp != null)
{
temp(www.progress / 3);
}
}
}
else
yield return www;
if (!string.IsNullOrEmpty(www.error))
{
Debug.LogError("Error while downloading data holder : " + www.error + "
calling error function");
Action temp = onError;
if (temp != null)
temp("Error while downloading data holder : " + www.error);
}
else
{
#if UNITY_EDITOR
if (debug)
Debug.Log(“Done downloading " + url + "
" + www.bytesDownloaded + " bytes downloaded”);
#endif
byte data = www.bytes;
www.Dispose();
byte[] decrypted = data.Decrypt(
SimpleConfig.getLine("pass", "UpdaterData"));
string path = Application.dataPath + "/" + pathToBases + "/" + ((DataHolder)CreateInstance(T)).pathToBase;
bool error = false;
try
{
File.WriteAllBytes(path, data);
}
catch
{
Debug.LogError("Error while writting base to file, calling error function");
error = true;
Action<string> temp = onError;
if (temp != null)
temp("Error while writting base to file");
}
if (!error)
{
#if UNITY_EDITOR
if (debug)
Debug.Log("Done saving " + T.FullName + " to " + path);
#endif
var bundle = AssetBundle.LoadFromMemoryAsync(decrypted);
if (update)
{
while (!bundle.isDone)
{
yield return new WaitForSeconds(updateRate);
Action<float> temp = onUpdate;
if (temp != null)
{
temp((bundle.progress + 1) / 3);
}
}
}
else
yield return bundle;
var dh = bundle.assetBundle.LoadAssetAsync(T.Name, T);
if (update)
{
while (!dh.isDone)
{
yield return new WaitForSeconds(updateRate);
Action<float> temp = onUpdate;
if (temp != null)
{
temp((dh.progress + 2) / 3);
}
}
}
else
yield return dh;
Action<DataHolder> temp2 = onDone;
if (temp2 != null)
{
temp2((DataHolder)dh.asset);
}
#if UNITY_EDITOR
if (debug)
Debug.Log("Done with data holder " + T.FullName);
#endif
}
}
}
}
and the class that call everything is there :
//Code written by Etienne Desrousseaux, alias FireCube, for the updater package.
//
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using UnityEditor;
using UnityEngine;
public class DataHolderWindow : EditorWindow
{
List<Type> types;
void OnGUI()
{
if (types == null)
types = new List<Type>(FindDerivedTypes(typeof(DataHolder).Assembly, typeof(DataHolder)));
foreach (var T in types)
{
if (GUILayout.Button(Regex.Replace(T.ToString(), "([A-Z])", " $0")))
{
open(T);
}
}
}
void open(Type T)
{
MethodInfo m = T.BaseType.GetMethod("GetInstance");
object j = m.Invoke(null, new object[] { T });
//T.GetMethod("open").Invoke(j, null);
}
public IEnumerable<Type> FindDerivedTypes(Assembly assembly, Type baseType)
{
return assembly.GetTypes().Where(t => t != baseType &&
baseType.IsAssignableFrom(t));
}
[MenuItem("Updater/Data Holder List")]
static void Init()
{
DataHolderWindow window = GetWindow<DataHolderWindow>();
window.titleContent.text = "Data Bases List";
window.Show();
}
}
The Debug are still in there
Thx
NEW EDIT :
I found the problem, but first, here’s my Demo class, that is the one that should open and create :
//Auto generated resource data holder the 7/3/2016
//Using the Updater package
using UnityEngine;
public class Demo : DataHolder
{
#region fields
public static new string name
{
get { return instance._name; }
set { instance._name = value; }
}
public string _name;
public static GameObject prefab
{
get { return instance._prefab; }
set { instance._prefab = value; }
}
public GameObject _prefab;
public static float speed
{
get { return instance._speed; }
set { instance._speed = value; }
}
public float _speed;
#endregion
public static Demo instance
{
get { return getInstance<Demo>(); }
}
[InspectorCallable]
public void Reset()
{
name = "";
prefab = null;
speed = 5f;
}
}
The problem is, indeed, the function Reset. Unity freeze when it’s not commented, but all is good if it is commented, and i can’t explain myself why…