Forum rules - please read before posting.

Remember whether a gameobject is enabled when save/loading

Hi! I'm bug fixing issues with out save load states. We have an object that gets enabled or disabled throughout the scene - it is a UI panel with many children, so we can't just use the build in Object Visibility action and then the Remember Visibility script on it. There is a constant ID on the object, but whether or not the object is disabled or not does not seem to save. Is there a work around for this?

Comments

  • edited January 2022

    Remember and ConstantID components will not be registered by the save system if they - or their GameObjects - are disabled.

    You can, however, use a Remember component on a separate GameObject that refers to the disabled object itself:

    using UnityEngine;
    using AC;
    
    public class RememberEnabled : Remember
    {
    
        public GameObject objectToSave;
    
        public override string SaveData ()
        {
            EnabledData data = new EnabledData();
            data.objectID = constantID;
            data.savePrevented = savePrevented;
    
            data.isEnabled = objectToSave.activeSelf;
    
            return Serializer.SaveScriptData <EnabledData> (data);
        }
    
        public override void LoadData (string stringData)
        {
            EnabledData data = Serializer.LoadScriptData <EnabledData> (stringData);
            if (data == null) return;
            SavePrevented = data.savePrevented; if (savePrevented) return;
    
            objectToSave.SetActive (data.isEnabled);
        }
    
    }
    
    
    [System.Serializable]
    public class EnabledData : RememberData
    {
    
        public bool isEnabled;
    
        public EnabledData () { }
    
    }
    
  • edited January 2022

    Does that mean component variables on an UI object aren't saved if the object happens to be disabled?

    Edit: opening a new thread for this.

  • Absolutely bizarre, the day you gave it to me, it worked, I set saveToObject, then packed up for the evening.

    Code is exactly the same, and if I try to save the game I get
    UnassignedReferenceException: The variable objectToSave of RememberEnabled has not been assigned.

    So it's definitely reading the script, it's just not allowing me to access that variable in the inspector

  • Ah, my fault. I forgot that the Remember base class has a custom Inspector - meaning that subclasses will not expose their own fields without an Editor script of their own.

    Place this additional script, RememberEnabledEditor, inside an Editor subfolder:

    using UnityEditor;
    using UnityEngine;
    using AC;
    
    [CustomEditor (typeof (RememberEnabled), true)]
    public class RememberEnabledEditor : ConstantIDEditor
    {
    
        public override void OnInspectorGUI ()
        {
            RememberEnabled _target = (RememberEnabled) target;
            _target.objectToSave = (GameObject) EditorGUILayout.ObjectField ("Object to save:", _target.objectToSave, typeof (GameObject), true);
            SharedGUI ();
        }
    
    }
    
  • Hey there, didnt' realize I hadn't replied to say thank you, this script worked great!

    At this point in development we've got 30+ objects in one of our scenes that need to remember enabled, and since all the copies of the script need to be on another game object it's becoming a bit of a mess. I've been trying to adapt this script into being a RememberEnabledMultiple with a List to keep all of the game objects in, but I've hit a bit of a wall with how it works. The SaveData function is a return string, so I feel like this return is going to be a single object. Is there another function I can call to cycle through a list of constantIDs to add to the save system?

  • edited October 2022

    You can reference as many objects as you like, so long as the serialized data class is made up of simple types. Here's a variant that supports multiple objects:

    using UnityEngine;
    using AC;
    
    public class RememberMultipleEnabled : Remember
    {
    
        public GameObject[] objectsToSave;
    
        public override string SaveData ()
        {
            EnabledMultipleData data = new EnabledMultipleData();
            data.objectID = constantID;
            data.savePrevented = savePrevented;
    
            data.isEnabled = new bool[objectsToSave.Length];
            for (int i = 0; i < objectsToSave.Length; i++)
            {
                data.isEnabled[i] = objectsToSave[i].activeSelf;
            }
    
            return Serializer.SaveScriptData <EnabledMultipleData> (data);
        }
    
        public override void LoadData (string stringData)
        {
            EnabledMultipleData data = Serializer.LoadScriptData <EnabledMultipleData> (stringData);
            if (data == null) return;
            SavePrevented = data.savePrevented; if (savePrevented) return;
    
            for (int i = 0; i < data.isEnabled.Length; i++)
            {
                objectsToSave[i].SetActive (data.isEnabled[i]);
            }
        }
    
    }
    
    
    [System.Serializable]
    public class EnabledMultipleData : RememberData
    {
    
        public bool[] isEnabled;
    
        public EnabledMultipleData () { }
    
    }
    

    And its Editor:

    using UnityEngine;
    using UnityEditor;
    using AC;
    
    [CustomEditor (typeof (RememberMultipleEnabled), true)]
    public class RememberMultipleEnabledEditor : ConstantIDEditor
    {
    
        public override void OnInspectorGUI ()
        {
            RememberMultipleEnabled _target = (RememberMultipleEnabled) target;
            int numToSave = _target.objectsToSave.Length;
            numToSave = EditorGUILayout.DelayedIntField ("# objects to save:", numToSave);
            if (numToSave != _target.objectsToSave.Length)
            {
                GameObject[] backup = _target.objectsToSave;
                _target.objectsToSave = new GameObject[numToSave];
                for (int i = 0; i < Mathf.Min (numToSave, backup.Length); i++)
                {
                    _target.objectsToSave[i] = backup[i];
                }
            }
    
            for (int i = 0; i < _target.objectsToSave.Length; i++)
            {
                _target.objectsToSave[i] = (GameObject) EditorGUILayout.ObjectField ("Object #" + i + ":", _target.objectsToSave[i], typeof (GameObject), true);
            }
            SharedGUI ();
        }
    
    }
    
  • Thanks! I'm getting an error I don't understand, though.

    Assets\Scripts\ExtendPlugins\RememberEnabledMultipleEditor.cs(6,46): error CS0246: The type or namespace name 'ConstantIDEditor' could not be found (are you missing a using directive or an assembly reference?)

    ConstantIDEditor is in the project, and the RememberEnabledMultipleEditor called on the AC library, so i'm not sure why this is happening.

  • Unity requires that Editor scripts need to be placed in "Editor" subfolders.

  • No errors now, but I don't see the objectsToSave list in the inspector?

  • Have you created new files, separate from the old pair, in the correct directories? I can't recreate the issue.

  • Sorry, I must have done something wrong. I went back and re copy-pasted the scripts you posted, and they worked now.

Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Welcome to the official forum for Adventure Creator.