List<T>, variable initialization inspector

I am having a weird issue here…

given this test code

[System.Serializable]
public class TestClass{
	public int test_int = 50;

   public TestClass(){
    Debug.LogError("constructor");
    test_int = 50;
   Debug.LogError("constructor_end = " + test_int);
  }
}

public class TestComponent: MonoBehaviour
{	
	public TestClass test_item;
	public List<TestClass> test_item_list;

I’ve no problem with the “test_item” member, is correctly displayed and its “test_int” has a value of 50 (with or without the constructor).

the “test_item_list” is empty and as soon as i change the size i get the constructor logs displayed in the console with the correct “test_int” value (50) but the value of “test_int” of the element displayed in the inspector is magically “0” !

is like the engine/inspector/whatever is doing the initialization using the default values that i’ve set (with or without the constructor) and after creating the element is doing a memset to 0 of all it’s content!
Any List will always set to 0 any parameter (int, float, enum) contained in the class!

where’s the trick?
is it an inspector/unity bug?

Not sure if this is the problem, but as far as I know, Unity doesn’t like constructors. Maybe use the Start or Awake function instead?

Constructors work fine in unity, they just can’t be called on classes inheriting from monobehaviour and as his TestClass isn’t inheriting from monobehaviour it has no Start/Awake function.

I’ve added that constructor only as a test (although there’s no problem with it), anyway also without it you would expect to see the test_int set to 50 in the inspector but that happens only if you declare a variable of type “TestClass”, if you define an array (TestClass[ ] test_array) or a list (List test_list) everytime you add an element all its members are set to 0…

also, let’s say that you have an element in your array/List and it’s member are set to certain values, if you add new elements to the array/list their value will always be a copy of the last element defined!

for instance in the previous code if you add an element to the list and set the “test_int” value to “20” and then change the size of the list from 1 to 10 to add new elements, all the elements “from 2 to 10” will have the “test_int” value set to “20” as well!

how can I make it so that it follows the default values that I want?

  1. Make it extend UnityEngine.ScriptableObject so the editor correctly serializes it. thats the class intend for editor used “serialized data containers” basically. If you use an own class with serializable, make a custom editor for the monobehaviour that uses it instead of using the auto reflection.

  2. One problem of making stuff serializable instead of having them scriptableobject is that they behave quite a bit different especially in the editor. they behave more like the original C99 structs (name mapped memory blocks) that get cloned upon growth of array / list, and the entry can never be null again in the editor due to serializable which tells the editor that there is something writable it must write so it will write and read it as if there were something in. this impacts the auto serialization with the inbuilt inspector

Hi dreamora and thanks first of all.

I’ve tried to create it as a ScriptableObject but it shows up in the inspector as a reference to a script instead of a “class/struct” with attributes like the one you get with the serialize attribute; do I have to write a custom inspector for it? I hope there’s an easier/faster solution…

the ScriptableObject doc page doesn’t really tellls much about them

EDIT

reading more about ScriptableObject on the web it looks like I have to create an instance in the editor using an editor script, and this instance will live as a separate asset in the project, not really what i want to do… i really need a simple struct to show up in the inspector with the default values i provide, any other way i could achieve it? or if you can tell me more about scriptableobject it would be great.

thanks

up

The inspector overwrites values of serialized items after construction. For the behavior the you want, you can set values on the constructed Data instances in Start or OnAfterDeserialize.

Take a look here:

3 Likes

OnValidate may also be of use.

Necro-post!

Lol, didn’t even see that!