Serialize Custom classes

I have the following c# script

public class Cheese  : MonoBehaviour
{
    // fields
    // start first 3 fields
    GameObject parent;
    GameObject[] connectors;
    int width, height;
    // end first 3 fields
    
    // start last 2 fields
    GameObject[][] blocks;
    BlockProperties bp; // this class is my custom class extending System.Object with [Serializable] attribute
    // endlast 2 fields
}

I have a Editor subclass for Cheese class
When I initialize all the fields of cheese class with Editor all fields initializes just fine.

When I click play button first 3 fields keeps their values but last 2 fields become null in run time. How can I fix that problem?

You can add the [System.Serializable] tag to serialize custom classes. Just add that attribute to BlockProperties.

Also look at SerializeField and NonSerializable if you want to be able to put private variables into the Inspector (or the backing fields of properties).

That however still doesn’t allow jagged arrays or multidimensional arrays.

One sorta hacky way is to have a GameObjectRow class that is serializable and overrides [ ] so that in code you can still use [1][2] to access it like a multidimensional array, but Unity can serialize it as an array of a custom class that has arrays.

Not ideal but it works for now.

A strong recommendation from my end:

Do never mark monobehaviour as serializable, it has major impacts on the editor behaviour and other aspects and can lead to totally untrackable bugs unless you know from experience where they come from

instead create a “model” class that contains the data and thats serializable and have a reference to it in the monobehaviour

2 Likes

Thanks for the reply.

i followed a way to solve multidimentional array problem. It is a different version of Ntero’s suggestion but it still has the same problem. I used the following class as multidimentional array but in runtime it becomes null.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityEngine.Serialization;
using UnityEditor;

[Serializable]
public class DoubleArray<T> : System.Object
{
    public int height, width;
    public T[] data;
    public DoubleArray(int width, int height)
        : this (width*height)
    {
        this.width = width;
        this.height = height;
    }
    public DoubleArray(int total)
    //: base(width*height)
    {
        data = new T[total];
    }
    public T this[int row, int column]
    {
        get
        {
            return data[row * height + column];
        }
        set
        {
            data[row * height + column] = value;
        }
    }
    public T this[int index]
    {
        get
        {
            return data[index];
        }
        set
        {
            data[index] = value;
        }
    }
}

also i forgot to write: All fields in my posts are public

I solved it in a bad way. When i remove from class name and a replace rest of the T’s with GameObject it worked. However i do not want to replace 'T’s with Gameobject. if you have such solution please share.

I see no problem making this work but you need to implement the serialization handling for such a custom class I think.

And naturally T must have the requirement to implement ISerializable, just some T can not work

yes dremora you are right.
since GameObject does not implement ISerializable

where T: ISerializable

does not solve my problem.
GameObject is marked with [Serializable] attribute and i dont know how to constraint T with [Serializable] attribute

i do not like my solution because i can not use that DoubleArray class for other classes than gameobject

Thats true
But if you don’t use ISerializable implementing classes you will be forced into hard binding, independent on if you want or not.

Also serializing a game object is of very limited use. What do you want to achieve in detail, perhaps there are better ways. Cause hierarchy serialization won’t work this way.