- Home /
How to get the instance of a ScriptableObject
I'm trying to make an Inventory system similar to the one from Skyrim and I have just finished item equipping. I have tried to make it so that if the player tries to equip an item that is already equip it de-euips. I have made that functionality by detecting if the item that is equip is the same as the item you are trying to equip (Using ==) it will de-equip that item. I am using ScriptableObjects with [CreateAssetMenu()] as the base class of my items. This way I have a template for my items and they are all .asset. The downside to this is that all of the items are considered the same, so if I try and equip a different copy of the same equipment .asset it de-equips the item. Is there a way I can save a unique instance id in my item class so I differentiate copies of the same template?
EDIT: Sorry, maybe I was misleading. I mean If I instantiate multiple instances of the same .asset, I need some way to differentiate between those objects, not just between different .assets from the same script.
I'm unfamiliar with scriptable objects... but it sounds like an easy way to store data about an object? Perhaps you could make some kind of enum or index for what kind of object instance it is? If you're allowed to give specific item classes specific attributes (string name, etc.) Then try messing around with that.
Answer by Joxev · Mar 05, 2020 at 10:47 PM
Hey, I found this thread
It solved my problem. After I did the solution I could just compare the two objects with an == operator.
Answer by dannyalgorithmic · Mar 05, 2020 at 10:00 AM
Perhaps you can fetch a get only integer ID using the GetHashCode function using the hash of the asset and class name in the OnValidate magic method as such ...
public int UniqueID { get; private set; }
private override void OnValidate()
{
int assetNameHash = name.GetHashCode();
int typeHash = typeof(type).GetHashCode();
int uniqueID = assetNameHash ^ typeHash;
if(Mathf.Approximate(this.UniqueID, uniqueID) == false) return;
UniqueID = uniqueID;
}
That being said, it won't immediately update when you alter the name of the asset, so you may have to the data to force a validation in order to correct the ID.
Might not be the best solution, but it's a solution.
I'm not sure that you understand, maybe my title was misleading. If I instantiate multiple instances of the same .asset, I need some way to differentiate between those objects, not just between different .assets from the same script.
Answer by ATLGAN · Mar 05, 2020 at 06:03 AM
You can find instance of ScriptableObject this way:
#if UNITY_EDITOR
public static ExampleData Load() {
string[] guids = UnityEditor.AssetDatabase.FindAssets("t:ExampleData");
if (guids.Length == 0)
{
return ScriptableObject.CreateInstance!!
}
else
{
string path = UnityEditor.AssetDatabase.GUIDToAssetPath(guids[0]);
return UnityEditor.AssetDatabase.LoadAssetAtPath
(path);
}
}
#endif
Editing: "return ScriptableObject.CreateInstance()" is not this before '()' ExampleData in <> same thing LoadAssetAtPath!!(path); But this code works only in Editor because this code is Editor code so it is inside in the '#if UNITY_EDITOR'.
I think you shouldn't use ScriptableObject for this because you can't save the information inside ScriptableObject in the Build. You need to use a save system for this. You can use like this:
public class TPP_DB { static string dataPath;
public static void Save(System.Object _saveObject)
{
if(_saveObject == null) return;
BinaryFormatter bf = new BinaryFormatter();
if(dataPath == null)
{
GetDirectory();
}
FileStream file = null;
if(!File.Exists(dataPath + "/Save/db.sav"))
{
file = File.Create(dataPath + "/Save/db.sav");
}
else
{
file = File.Open(dataPath + "/Save/db.sav", FileMode.Open);
}
if(file != null)
{
bf.Serialize(file, _saveObject);
file.Close();
}
}
public static TPP_Data Load()
{
if(dataPath == null)
{
GetDirectory();
}
if(dataPath != null)
{
if(File.Exists(dataPath + "/Save/db.sav"))
{
BinaryFormatter bf = new BinaryFormatter();
FileStream file = File.Open(dataPath + "/Save/db.sav", FileMode.Open);
TPP_Data loadedData = (TPP_Data)bf.Deserialize(file);
file.Close();
return loadedData;
}
else
{
return null;
}
}
else
{
return null;
}
}
static void GetDirectory()
{
string[] paths = Directory.GetDirectories(Application.dataPath, "TerrainPathPainter", System.IO.SearchOption.TopDirectoryOnly);
if(paths.Length > 0)
{
dataPath = paths[0];
dataPath = dataPath.Replace('\\', '/');
dataPath = dataPath.Substring(dataPath.IndexOf("Assets"));
}
}
}
Hey, I'm not sure how I would get a instance or id an id of a ScriptableObject from the load function. Could you explain a little bit more?