Hi guys. I have one SciptableObject (SO) which contains list of attached prefabs to it. Also i have one MonoBehaivour (MO) which select some prefab from SO, and for exmaple instantiate prefab in scene. But i have a problem. When i press “reset” on MO component in inspector it removes the gameobject from list in SO. So, as i understand it happens because MO keep link to gameobject in SO, and reset function null this link even in SO. But, i dont quite understand how should i avoid this behaivour? i tryied to use set/get consrutction to make it like “read only”, but it does not help. How can i avoid removing object from scriptable when reset function is called on monobehaivour?
public class Sciptable : ScriptableObject
{
public List<GameObject> list;
}
public class Mono : MonoBehaviour
{
public GameObject selectedObject;
public void SelectObject(int index)
{
Sciptable so = AssetDatabase.FindAssets("bla bla bla");
selectedObject = so.list[index];
}
}
No, this can’t happening. When you reset the MonoBehaviour it has absolutely nothing to do with your SO asset in your project. You have editor code (your “SelectObject” method) that does use the AssetDatabase to reach out to the SO asset and read one of its values, however the SO object itself is not referenced by your MonoBehaviour object at all. You only store a reference to one of those prefabs in the variable of your MonoBehaviour. Of course, this reference would be gone when you reset your MonoBehaviour. However resetting the MB can’t have an effect on the SO.
Oh, excuse me! I tried to simplify my problem and skip some details.
I changed it a little, now its like as it is in my project.
Repeat:
Create SO.
Add list item.
2.1) Add some prefab to list item
Select it through the MonoTest
Reset MonoTest
Check the SO
[CreateAssetMenu(menuName = "SO TEST")]
public class SOTest : ScriptableObject
{
[SerializeField] public List<SomeClass> listOfItems;
}
[System.Serializable]
public class SomeClass
{
[SerializeField] public GameObject someObject;
}
public class MonoTest : MonoBehaviour
{
public SomeClass selectedClass;
public GameObject currentObject;
[ContextMenu("SELECT PREFAB")]
public void SelectPrefab()
{
SOTest soTest = AssetDatabase.LoadAssetAtPath<SOTest>("Assets/SOTest.asset");
selectedClass = soTest.listOfItems[0];
currentObject = selectedClass.someObject;
}
}
Well, that’s a different story and what you do here is actually dangerous if you keep in mind how Unity’s serialization system works. Custom serializable classes are usually serialized “inline” and behave like a struct when it comes to serialization. However if they are classes, of course in memory they behave like classes. What you have done here is copy a “reference” to the custom class instance to your monobehaviour. So both, the MB and the SO are seeing / using the same class instance. However when your MonoBehaviour is actually serialized, it would have it’s own instance of that class. Though since you probably pressed Reset right after “copying” the reference, both are still using the same instance. So resetting the MB would clear the fields in that custom class since the MB thinks that class belongs to itself.
Since you can not properly “reference” SomeClass instances, I would recommend to either switch that class to a struct, or when you want to select a certain element, either create a copy of the class (that requires you to implement a copy constructor yourself) or by not storing a reference to the class instance but maybe just the index into the list inside the SO.