Something about my current set up for saving is causing my array to not function.
I have an array that holds the names of objects I buy from a store, when you click a button, those object icons load on top of square sprites in order.
I had a problem with it creating empty variables when the list ended so I now have an extra part to specify to not run the code if there isn’t currently a child there.
I also have to start the scene with 2 child variables already in the list because it doesn’t work otherwise, idk why.
When I hit load, the number of children in the array goes up to the correct loaded amount but only the 2 variables that were already in the list actually spawn, none that were saved.
I need to have the full list of objects to spawn in.
I tried every combination of clearing the storage, clearing the variables, but I can’t get it to work.
I suspect that there could be some empty variable spawning through save/load which causes a break in the list or something but I’m not sure, there is no extra child variable that I can see.
The variable is a global variable and everything works fine until it comes to save/load.
It’s only updating the childamount variable once (at the beginning) If the size of the array changes then the variable needs to be updated. Like after loading.
It would be easier to use the number of children expression instead of a variable. Then it would always be the current size.
Short version: your instinct is right, and the mechanism is specific enough to test in a minute.
Two engine facts are doing this:
1. Array variables can hold empty slots, and “child count” counts them.
If anything ever writes to an index past the end of the array, every slot in the gap becomes an empty element. In GDJS/Runtime/variable.ts, getChildrenCount() for an array just returns _childrenArray.length (holes included), and getChildAt(i) on a hole creates an empty variable in that slot instead of reporting “nothing here”. So VariableChildCount(array) can be correct while the real entries are fewer, and a “does this child exist” check can pass on a slot that holds nothing. That is probably why your guard does not catch it.
2. The save/load round trip turns those holes into the string "null". toJSObject() pushes undefined for a hole. JSON.stringify writes undefined inside an array as null. On the way back, fromJSObject(null) runs this.setString('null') (variable.ts, around line 310). So after a load you get real children whose value is the text null, not empty ones. Count looks right, existence checks pass, and none of them spawn anything, because "null" is not one of your object names. Only the entries that were never holes survive.
30-second test:
Before saving, log the array as JSON (set a text object to ToJSON(YourArray), or print YourArray).
After loading, log the same thing.
If "null" shows up in the loaded version, that is it.
Fixes, most reliable first:
Never leave gaps. Append using VariableChildCount(array) as the index instead of picking an index yourself. If you need to mark “end of list”, use a separate count or a sentinel value, not an empty slot.
Do not cache the count in its own variable (same thing Keith_1357 said). Ask for the number of children at the moment you need it.
If you want named slots, store a structure (item0, item1, …) or one delimited string. A structure has no holes, so it round-trips clean.
One more thing that surprises people: loading into a variable that already exists does clear it first (fromJSObject calls clearChildren() for arrays and structures), so you do not need to clear it by hand. If old entries survive a load, the load is not landing in the variable you think it is.
Post your save and load events (or the two JSON logs) and I will point at the exact line.
The first array position is 0, which means the last one in VariableChildCount(…) - 1. So if array MyArray has 5 elements , the first one is MyArray[0] and the last is MyArray[4].
In the event snip below, the child event will eventually set Boxorder to childamount, and on the next iteration it accesses Saveddecor1[Boxorder]. This is past end of the array and will add a new blank element:
That’s because you set the variable childamount at the very beginning withou having loaded the saved array first. The last 2 events in your screen snip need to be added before you set the value of childamount in the beginning of scene event.