This is pretty much how to save a scene if you want to do it the same way as the Godot Editor does. And because of that, indeed variables without export are not saved, that’s just how it works. You could make them export but then they would end up being saved from editor too (unless you are fine with that).
Note that it can’t save all vars either, some types are not suitable for that. On top of that, how would it know which vars must be saved?
Keep in mind PackedScene saves a lot of things. If you want to use it for a game save, you’ll be constrained to what it was made for. Otherwise, making your own system could be more work but at least you can save what you want (and it’s actually not hard, you can get the path of the scene to recreate later with node.filename, and make lists of vars you want to save and use get and set to initialize them).
Maybe you could save with PackedScene, and write another file next to it with the missing variables but then that would end up into a custom save system anyways.
In theory, I think you could trick PackedScene and mark specific vars with USAGE_STORAGE if Engine.editor_hint == false, but doing that is a bit painful as it forces you to override _get_property_list(), like this untested code:
# These are not saved by the editor and not shown either
var my_number = 42
var my_text = "Hello"
func _get_property_list():
if Engine.editor_hint:
return
# But in game, Godot will see this
return [
{
"name": "my_text",
"type": TYPE_STRING,
"usage": PROPERTY_USAGE_STORAGE
},
{
"name": "my_number",
"type": TYPE_INT,
"usage": PROPERTY_USAGE_STORAGE
}
]