Home > Back-end >  How to assign GameObject to child for serialization
How to assign GameObject to child for serialization

Time:02-14

I want to assign each item I create with a GameObject of some sort and then when I create a new object (called Item) it will have the assigned GameObject as a child.

For that I have a class of a scriptable object which holds a public GameObject called "gameObj" within it:

public abstract class ItemObject : ScriptableObject
{
    public int id;
    public GameObject gameObj;
}

Then, in another class I want to have something of this sort:

public class GroundItem : MonoBehaviour, ISerializationCallbackReceiver
{
    public ItemObject item;

    public void OnBeforeSerialize()
    {
        this.gameObject.transform.GetChild(0) = item.gameObj; //WRONG CODE, NEED HELP HERE
    }
}

The purpose is to set the gameObj from the given ItemObject.item as the GameObject for the GroundItem.

The purpose is in the end to have lots of scriptable items of all sorts (like bread, sword, stone etc) and each one will have a GameObject assigned to it, and once I create a new GroundItem game object I will simply assign the scriptable object item and its child will have the game object itself (which includes all the visuals, special scripts etc).

For reference, in the following link the person is doing this from minute 4 to minute 6, but with a sprite instead of a game object.

Anyone knows how it should be written? Is it even possible?

CodePudding user response:

You would probably mean

public class GroundItem : MonoBehaviour, ISerializationCallbackReceiver
{
    public ItemObject item;

    public void OnBeforeSerialize()
    {
        if(!item) return;
        if(!item.gameObj) return;

        // make according object a child of this object
        item.gameObj.transform.parent = transform;

        // make it the firs child
        item.gameObj.transform.SetSiblingIndex(0);
    }
}

However, in general ScriptableObjects are assets and GameObjects are instances in the scene hierarchy -> you can't simply reference scene objects in assets, doing so anyway might lead to unexpected behavior.

Is there a good reason why this has to be done in ISerializationCallbackReceiver?

I think what you actually rather want to achieve would be e.g.

public class GroundItem : MonoBehaviour
{
    public ItemObject item;

#if UNITY_EDITOR
    [HideInInspector]
    [SerializeField]
    private ItemObject _lastItem;

    // This is called whenever something is changed in this objects Inspector
    // like e.g. item ;)
    private void OnValidate()
    {
        // Delay the call in order to not get warnings for SendMessage
        UnityEditor.EditorApplication.delayCall  = DelayedOnValidate;
    }

    private void DelayedOnValidate()
    {
        // remove the callback since we want to be sure it is always added only once
        UnityEditor.EditorApplication.delayCall -= DelayedOnValidate;

        // if item hasn't changed nothing to do
        if (item == _lastItem) return;

        // otherwise first destroy current child if any
        if (_lastItem && transform.childCount > 0)
        {
            if (Application.isPlaying) Destroy(transform.GetChild(0).gameObject);
            else DestroyImmediate(transform.GetChild(0).gameObject);
        }

        // is an item referenced and does it even have a gameObject ?
        if (item && item.gameObj)
        {
            // instantiate the new one as child of this object 
            var obj = Instantiate(item.gameObj, transform);

            // set as first child (if needed)
            obj.transform.SetSiblingIndex(0);

            if (!Application.isPlaying)
            {
                // if in edit mode mark this object as dirty so it needs to be saved
                UnityEditor.EditorUtility.SetDirty(gameObject);
                UnityEditor.SceneManagement.EditorSceneManager.MarkSceneDirty(UnityEditor.SceneManagement.EditorSceneManager.GetActiveScene());
            }
        }

        _lastItem = item;
    }
#endif
}

Which would now look like

enter image description here

  • Related