Save/Load the Properties of Objects using globalDict or cPickle

Saves and loads the properties of objects in active scenes.
The new version also saves the position and orientation of the objects.

Note:
Objects must have a property named “save”.

Only works for objects in active scene such as overlay scenes.
The end result is a Dictionary of every objects name,
under each name is the stuff saved for that object.
The Dictionary is then saved to a file called saveLoadProperties.dat.

saveLoadProperties.dat <-- GameLogic.globalDict <-- Object.name <-- Object’s stuff

#                            saveLoad.dat
#                                 |    
#                        GameLogic.globalDict
#                    _____________|_______________
#                    |                           |
#                 Suzanne                       Cube    
#               _____|_____                 _____|_______
#               |         |                 |           |    
#            propList  position          propList    position

Blend Files:

s - to save the properties.
L - to load globalDict and replace properties.
space - to move the Cube and increment variables.

Updates
25-Jun-09:
Saves the properties of objects in all active scenes.
I believe this requires 2.49a. because its using "if “save” in object:"saveLoadProperties_2.49a_1Script.blend (180 KB) 180kb
saveLoadProperties_2.49a_2Scripts.blend (181 KB) 181kb

28-Jun-09:
This version also saves the position and orientation of the objects
There’s some good info on using globalDict here
http://www.tutorialsforblender3d.com/GameModule/GameLogicModule_20.html

saveLoadProperties_1Script_02.blend 183kb

08-Aug-09:
cPickle The Dictionary is now saved to a file using cPickle (mentioned by Sim88) instead of using the Logic bricks.
(pickling aka serialization or marshaling)
please let me now if it works for you.saveLoadProperties_pickle_Aug08-09.blend (188 KB) 188kb
12-Sep-09: cPicklesaveLoadProperties_pickle_Sept12-09.blend 187kb
Just an improvement to avoid errors.

Implementation scene changing .Link 21-Aug-09; Two example of seamless scene changing.
Link 29-Aug-09; Another scene changing example with mouse look.

You really don’t need to save the global dictionary to a file when switching scenes,
because whatever is in globalDict remains the same while switching scenes.
Terms Of Use
You are free to use the files posted by me in this thread in any way that you would like.
But a little credit would be nice.
I hope someone will find it useful.

Hello
it works very well in my Debian/GNU/Linux 64!
And very easy to use!
Thank you very much for sharing!
Bye

Nice to see someone use save/load globalDict actuator. I haven’t tried yet so this is a useful resource. I usually write and read textfiles with python. I have a script using pickles and gzip for compressing, which is good if you want multiple save files to be unreadable to the naked eye. Or just have a small file sizes.

how do I save the scene in which it is

Hi,
I updated the code. works with all active scenes.

diskette, sorry, I’m not sure what your asking.

This saves all the properties in a dictionary under the name of the object the properties belong to.
When you load, it gets a list of all the objects you want to save, it then checks the globalDict
to see if the objects properties have been saved, and replaces them if they have.

help me, I’m putting more properties to objects such as position, orientation and the scene where they are, I can save but I’m having trouble loading! help me!


#-----[ Save Properties ]------------------------------------------------------
# Blender 2.49
# PhilB June-03-2009
# Object must have a property named "save" for its properties to be saved
# The globalDict is saved in the same place as the blend file
# with the extension .bgeconf.
g = GameLogic
c = g.getCurrentController()
own = c.getOwner()
scene = g.getCurrentScene()
save = c.actuators["saveGD"]
## Get a list of all objects with a property named "save".
#obList = [object for object in scene.objects if object.has_key("save")]
obList = scene.objects
  
_scene = scene.getName()
c.activate(save)
for obj in obList:
  _name = obj.name
  _position = obj.getPosition()
  _orientation = obj.getOrientation()
  _propName = obj.getPropertyNames()
  propList = []
  for p in _propName:
   val = obj[p]
   propList.append(val)
  g.globalDict[_name] = (list(_scene)) + _position + _orientation + _propName + list(propList)
 
print "
Save
",g.globalDict


#-----[ Load Properties ]-----------------------------------------------------
# Blender 2.49
# PhilB June-03-2009
g = GameLogic
c = g.getCurrentController()
load = c.actuators["loadGD"]
c.activate(load)
scene = g.getCurrentScene()
## Get a list of all objects with a property named "save".
#obList = [object for object in scene.objects if object.has_key("save")]
obList = scene.objects
if g.globalDict:
 _scene = scene.getName()
 for obj in obList:
  _name = obj.name  
  _propVals = g.globalDict.get(obj.name)
  _propName = obj.getPropertyNames()
  _position = obj.getPosition()
  _orientation = obj.getOrientation()  

  for x in range(0,len(_propVals)):
    obj[_name[x]] = _scene[x] + _position[x] + _orientation[x] +_propName[x] + list(propVals[x])
  
   
 print "
Loading
",g.globalDict
elif not g.globalDict:
 print "

Error: No globalDict found.
"

Hi,
There’s some good info on using globalDict here
http://www.tutorialsforblender3d.com/GameModule/GameLogicModule.html

In the Save script:

stuff = {     "propList" : propList,
              "position" : obj.localPosition,
              "orientation" : obj.localOrientation    }
        
GameLogic.globalDict[obj.name] = stuff

In the Load script:

theStuff = GameLogic.globalDict.get(obj.name)

obj.position = theStuff["position"]

And here’s an updated blend.

Edit: btw, it doesn’t hurt to figure things out on your own.

Attachments

saveLoadProperties_1Script_02.blend (183 KB)

Still perfect, still excellent, still thank you, for sharing! :wink:

I’m trying to get a loading system for a game i’m making. i want to save the position of the character and load in a new scene, but i am having problems. The scene loads, the character seems to be in place, but the new scene seems to not recognize that the character moved. I kind of want the scenes to work like layers, it seems like i have to make a new character for every scene, if i did that, then the save load doesnt work, because the names of the object change per scene. What i’m trying to do is load in a new area of a level when he opens a door. I was hoping to use the saveload script to remember his location to make the transition seamless.

but the new scene seems to not recognize that the character moved.
I’m not sure what you mean by that… Are you walking through an open doorway? or do you want the player to start at specific position in the new scene, and remember the position he came from?

you might want to look at this Dynamic Loading/Freeing Pledge.
And check these out [Script] Seamless scene changes
go to different scene, in the same place relative to an empty

One thing would be to link the player into each scene, and have predefined positions for each doorway in each scene, then, depending on where you’re going and where you came from set your player to one of these points.

Or you can use own version of Sam’s seamless scene changing script, this requires all the doorways to be lined up with each other.
and a here’s an overly complicated example using empties.:slight_smile:

Attachments

SeamlessSceneChangingPhilB.blend (333 KB)sceneChangeTest_15_playerGroup.blend (233 KB)

what better way to save the current scene name, type my player has its position and orientation at the scene “Level_1” when I go to another blend with the scene “Level_2” he carries the position and orientation of the “Level_1” kind would not how to create a file “saveLoadProperties.dat” for each scene?

See my project and video: http://blenderartists.org/forum/showthread.php?t=163739

decided:

#-----[ Save Load Properties ]------------------------------------------------------

Blender 2.49a

PhilB June-28-2009

Object must have a property named “save” for its properties to be saved.

Saves and loads the properties of objects in active scenes.

This version also saves the position and orientation of the objects

#-----[ Updates ]-----#

Aug 06-09

Saves the GameLogic.gobalDict to a file using cPickle

(pickling aka marshaling)

Better than using the logic bricks in my opinion.

Aug 07-09

Using Module with functions

Aug 07-09

Removed the stupid modules and functions

#-----[ Controls ]-----#

S key to save

L key to load

space to move Cube and increment a variable

#-----[ Main ]------------------------------------------------------------------
import cPickle, shelve

import GameLogic

c = GameLogic.getCurrentController()
owner = c.owner
sceneN = GameLogic.getCurrentScene()
sceneName = sceneN.getName()
save = c.sensors[“S”]
load = c.sensors[“L”]

#-----[ Object List ]---------------------------------------------------------

Gets a list of every object in every active scene

that you want to save.

sceneList = GameLogic.getSceneList()

saveObjList = []

for scene in sceneList:
for object in scene.objects:
if “save” in object:
saveObjList.append(object)

#-----[ Save ]---------------------------------------------------------------

Save the properties of every object in the saveObject list.

The end result is a Dictionary of every objects name,

under each name is the stuff saved for that object.

The Dictionary is then saved to a file.

saveLoad.dat <-- GameLogic.globalDict <-- Object.name <-- Object’s stuff

saveLoad.dat

|

GameLogic.globalDict

|

| |

Suzanne Cube

| |

| | | |

propList position propList position

if save.positive and save.triggered:

for obj in saveObjList:
propNames = obj.getPropertyNames()
propList = []
for p in propNames:
val = obj[p]
propList.append(val)

stuff = { “propList” : propList,
“position” : obj.localPosition,
“orientation” : obj.localOrientation }

GameLogic.globalDict[obj.name] = stuff

#pickle_file = open(“saveLoadProperties.dat”, “w”)
pickle_file = open(“saveLoadProperties_”+sceneName+".dat", “w”)

cPickle.dump(GameLogic.globalDict, pickle_file)

pickle_file.close()

print "

Saving:
"
for obj in saveObjList:
print obj.name
print GameLogic.globalDict.get(obj.name)

#-----[ Load ]---------------------------------------------------------------
if load.positive and load.triggered:

try:
#pickle_file = open(“saveLoadProperties.dat”, “r”)
pickle_file = open(“saveLoadProperties_”+sceneName+".dat", “r”)
GameLogic.globalDict = cPickle.load(pickle_file)
pickle_file.close()

except(IOError), e:

print “”"
ERROR: You’ve got to save the bloody file first before
you can load it! or as python would say:

“”", e

else:
for obj in saveObjList:

theStuff = GameLogic.globalDict.get(obj.name)

Replace the object’s properties with the saved ones.

savedProps = theStuff[“propList”]

objProps = obj.getPropertyNames()

for x in range(0,len(savedProps)):
obj[objProps[x]] = savedProps[x]

Load the position and orientation

obj.position = theStuff[“position”]

obj.localOrientation = theStuff[“orientation”]

print "

Loading:
"
for obj in saveObjList:
print obj.name
print GameLogic.globalDict.get(obj.name)


[LEFT]I created the runtime and not worked, maybe not uploaded any library
** PC (AMD Sempron ™ Processor LE-1100 1.90GHz, 1GB Ram, nVidia8400GS, Vista Bussiness / Ubuntu 9.04)
works in windows but in ubuntu this error occurs.[/LEFT]

You really don’t need to save the global dictionary to a file when switching scenes,
whatever is in globalDict remains the same while switching scenes.

You could even use something simpler like this,

currentScene = GameLogic.getCurrentScene()
GameLogic.globalDict[currentScene.name] = owner.localPosition

Then, run something like this when you enter a new scene

currentScene = GameLogic.getCurrentScene()
if GameLogic.globalDict.has_key(currentScene.name):
    owner.position = GameLogic.globalDict[currentScene.name]

This wont work if you can enter a scene from more than one location and it might give you more problems as well.
I still think Its best to have predefined starting points for each scene, something similar to the second example I posted above.

But what ever works for you, it’s your game.:slight_smile:

Edit: You forgot the code tags:), and you didn’t have to re-post all the code, I’ve got it! lol.
I’m not sure whats wrong because I don’t know how you’re implementing it.
I don’t know about the Ubuntu problem.
And for runtimes you have to get the pickle.py found in C:\Python26\Lib and include it with your file somehow (I’ve never done it.)

Here is a video link to the game i’m working on. the 2nd demo you showed me looks promising. i havent had time to test it out. From seeing it im assuming i need to have a character in every scene. Can you please watch the vid and give me some advice. thankshttp://www.youtube.com/user/carlosandlexi

Cool i got one of the demos to work (player_group). I never knew about the new scene LinkObjData, i always just copied scene. I still dont really understand it, but i did get it to work in my own file. There is still a few things wrong. The first problem is that i’m using an empty in the middle of a doorway as the spawn point, the thing is my doorway is a little wide. My characters rotation i carried over correctly, but his location snaps to the empty right in the middle. (it would work fine if i always entered the door in the middle but thats not what i want) I’m wondering if I could also have the empty move and track where the character crosses the door, and carry the location over to the next scene that way its more seamless. Now my other problem is this, I appended the cube/player group for the blend into my file, in order to practice, but i placed a camera over the cube in order to get it set for a FPS rig, like i said it was working fine with the motion script, except i didnt have a mouse look set in yet. Figuring it would just be a matter of putting in the script and giving the camera a save property it would work fine, i was wrong. I only seems to save the movement form the motion script, and not the mouse look script. What happens is when i move with the keys and dont touch the mouse it works fine, (except the first problem of course) but when i use the mouse to look around and it rotates the character it dosent carry over when i cross the load scene boundry, it just spawns in the same place it should spawn its just resets the rotation. Dude if you could help me out with this it would be super awsome. It would take me to a whole new level of badassness. Your my only hope.lol

http://www.mediafire.com/?sharekey=%20d1faf478cd4f608108f8df73f2072ed6e04e75f6e8ebb871

that is a link to my media fire files, it the one labled loading test 2.blend

Hi,
That mouselook script was way overly complicated and really messing everything up for some reason.
So I removed whatever wasn’t necessary in the code and now it works fine.

Loading a scene like this might not be the best thing to do,
because the whole game will freeze for a couple of seconds.
But right now I don’t know the best way.

Attachments

loading test 9.blend (252 KB)

Thanks so much. I got the file and it works awsome. This is just what i wanted it to do. I know it has a little hicup but whatever works. Thanks again.

Awesome stuff PhilB

I’ll be using this in the game I’m working on at the moment, youve saved me hours and days worth of coding to work this out, and I probubly would have done it in a less efficient way anyways.

Thanks a million!

Hi PhilB,

I was taking a look at your file. This is a very interesting resource, thank you for sharing.
I have a question about cpickle (I have searched the docs and will keep on, but if you knew the answer that would help a lot) :

  • How to save / update only one variable in an existing dictionary (in"saveLoadProperties.dat")?
  • How to extract/load only one variable from an existing dictionary (in “saveLoadProperties.dat”)?

Thank you!

Hi Cray,
I’m saving each object’s property values in a list, that makes it impractical to update and load a single variables.

I made this script so you wouldn’t have to worry about saving and loading individual variables.
But I updated the code, You can now update object’s variables if you want to.
It could still be improved more though.

Update property:

GameLogic.globalDict[obj.name]["propList"]["prop"] = obj.prop

Load property:

obj.prop = GameLogic.globalDict[obj.name]["propList"]["prop"]

I’m not 100% sure the above examples work.
here’s the new file.

I you want to update individual elements in the file itself, then you need to use the shelve module. It allows you to save everything to the file like a dictionary so you can access things randomly.
Here’s a shelve test I made.

It’s not the best example, hope it helps :slight_smile:

Thank you very much, PhilB.
My problem was that when restoring properties, I wanted some properties to remain unchanged.
I download now and start studying.

I you want to update individual elements in the file itself, then you need to use the shelve module. It allows you to save everything to the file like a dictionary so you can access things randomly.
That should answer my question.

Thank you very much, it will surely help :slight_smile:

EDIT
I have upgraded the file using the shelve module :

  • to store a list of objects
  • a bit of layout in the python console for beginners to have a better understanding of what’s happening (that’s the one I’ve used to learn about your file)
    My little contribution to your good thread.

Attachments

saveLoad pickle shelve test 11_list.blend (145 KB)