some objects work but not others in the object list

I just found a problem in a scrpit I made. I used the objList thing and suddenly some objects could be found, but not other. I get the error report -->KeyError:“´´OBHj1´´ not in list”<-- (without the arrows). Here’s a cut out from the script.

import GameLogic

cont = GameLogic.getCurrentController()
scene = GameLogic.getCurrentScene()
objList = scene.getObjectList()

Empty1 = objList["OBEmpty1"]
Empty2 = objList["OBEmpty2"]
Empty3 = objList["OBEmpty3"]
Empty4 = objList["OBEmpty4"]
Empty5 = objList["OBEmpty5"]
Empty6 = objList["OBEmpty6"]
Empty7 = objList["OBEmpty7"]
Empty8 = objList["OBEmpty8"]
Empty9 = objList["OBEmpty9"]

Hj1 = objList["OBHj1"]
Hj2 = objList["OBHj2"]
Hj3 = objList["OBHj3"]
Hj4 = objList["OBHj4"]
Hj5 = objList["OBHj5"]
Hj6 = objList["OBHj6"]
Hj7 = objList["OBHj7"]
Hj8 = objList["OBHj8"]
Hj9 = objList["OBHj9"]
Hj10 = objList["OBHj10"]
HjKn = objList["OBHjKn"]
HjD = objList["OBHjD"]
HjK = objList["OBHjK"]

The strange thing is that the Empty1-9 works fine, but not the Hj1. (and then probably the rest of the Hj ones) The Hj objects are planes that I added recently, while the Empty1-9 are empties that I’ve had for a while.

Any ideas of what could have caused this? I googled on it and found this error mentioned once and then without a sulotion.

Must they be on layer one to work? Seems so, because, when I moved Hj1 to layer one it said “Hj2 is not in the list” instead… But shouldn’t it be possible to add objects from a second layer in Python? Do anybody have a clue to what I can do to get it working?

you could try adding the code:


for obj in objList:
     print obj.name

to see exactly what objects are being returned by getObjectList(). This will print out the names of all the objects in the list to the console. A very handy technique for debugging ;).

Edit: I just tried this with a plane on a hidden layer, and the plane doesn’t show up in the list.
Using the Edit Object actuator with Add Object and the name of the plane (“Plane”), the plane was added to the scene and the list. It seems that getObjectList() does indeed return only the visible objects and not objects on hidden layers.

Edit 2: You could confirm this by showing both layers and then running the game with the print statement to see if all objects on visible layers are in the list, but I think this will be the case.
I’m not sure how you’d go about the task of creating a list of objects that are hidden that could be added using the Add Object actuator with Python at runtime. Maybe create a data text file using a script from Blender that will list all objects that are on hidden layers. This can then be read back by the game to create a global list for reference.

Edit 3: Globals are created by adding a property to GameLogic using code such as:


GameLogic.globalList = []          #initialises the global list
 
GameLogic.globalList.append("name of object here")          #adds an item to the list
GameLogic.globalList.append("another object")          #adds another item to the list
 
for listItem in GameLogic.globalList:          #prints out the contents of the global list
     print listItem

You will only want to do this once so you would need to test for the existence of the global list before initialising it, using a technique such as:


if not hasattr(GameLogic, "globalList"):          #if GameLogic doesn't have the property globalList
     #initialise the global here
     GameLogic.globalList = []

Methods and properties of the KX_SCA_AddObjectActuator class can be found in the Blender Game Engine Python Functions.

Thanks very much! :smiley: I’ll be looking for a way to get the objects from the global list, so I can add them. Both GameLogic.globalList(“OBHj1”) and GameLogic.globalList().getObject(“OBHj1”) returns the Error message: “TypeError: ‘list’ object is not callable”.

EDIT: Looked it up and saw a thing in a scrpit, which made me change the code to something like this (this is picked out from separate parts of the script following the Hj1 object from being added to global list to being placed):

Empty1 = cont.getActuator("Empty1") #Get the actuator that places Hj1
OBHj1  =  GameLogic.globalList.append("OBHj1") #Adding Hj1 to the global list
Hj1  =  OBHj1 in GameLogic.globalList  #Finding Hj1 in the global list
if z1==1:
    Empty1.setObject(Hj1) #Placing Hj1

I’m not done yet, so I’m left to see if all works, but it actually seems so. :slight_smile:

EDIT2: Whoops, that wasn’t right… Better try again…

I kind of feel rather stupid, but I can’t figure out how I’m going to use the globalList… I can guess, but I’d most likely just try forever without results.

Edit: This post may either be confusing or informative. See the post below. :wink:

The implementation I was thinking of for the global list was to store a list of strings containing the names of hidden objects. The Add Object actuator can add objects by name and this name could be retrieved from the list.

I think you are getting the error because you are storing a list of strings but are trying to reference the object with that name. ie. calling the string rather than the object.

The method that I was thinking of was to automate the setting up of the global list as much as possible. I was thinking that you could create a list of strings before the game runs and then read in the list at runtime to set up the GameLogic.globalList. This would enable an arbitrarily large number of hidden objects to be used by the game. If you wanted to hard code the creation of the list then the number of objects would be limited by the time that you want to spend creating the list.

I don’t really understand what you’re trying to do. If you’re trying to add a hidden object to the game at the location of an empty then you’d want to use an Edit Object actuator, set the name of the object to add using setObject(“name of object here”) and use the instantAddObject() method of the actuator.

If the global list holds a list of strings:


#initialise the global list as above, then...
 
gl = GameLogic.globalList
gl.append("OBHj1")
gl.append("OBHj2")
gl.append("OBHj3")
 

Assuming you’ve got the add object actuator, the list could be used like this:


for objName in GameLogic.globalList:
     actuator.setObject(objName)
     actuator.instantAddObject()
     addedObject = GameLogic.getObjectList()[objName]
     empty = GameLogic.getObjectList()["OBEmpty"]
     addedObject.setPosition(empty.getPosition())

This code snippet might have bugs, I’ve not checked it, but it should add all hidden objects to the scene whose names are stored as strings in the global list. It will then retrieve the object from the scene’s object list (so you can work with the object and not just it’s name), it will then retrieve the empty from the scene’s object list and set the position of the newly added object to the position of the empty.

It will set the position of every added object to the position of the same empty. If you want to use different emptys then you would need to change the name of the empty whose position you want to use. This could be done using string manipulation, like take the number of the added object and add that to the name of the empty that you’re using. I’d suggest you learn a little about string manipulation in Python to do this. Byte of Python is a pretty good beginner’s online book that explains this.

Edit: If you want to store both the name of the object and a reference to the object itself in a list then you might be better off using a dictionary. You can then use the name of the object to reference the object itself. To actually form the dictionary containing the objects though you’d need to add them to the scene in order to get a reference to them. It’s a bit of a catch 22 situation because it seems that a reference to an object can only be retrieved after the object has been added to the scene. Since the add object actuator can use either a reference to an object or the name of the object I was thinking that you would want a list of object names. If you are going to be adding a specific object at a specific event then the list might not be needed and you could simply hard code each added object setting each object to add by name using setObject(“OBname”) and then using instantAddObject() to add that specific object to the game. It’s hard to sort this issue since I’m not sure what you’re trying to do.

I’m going to double post since this post is a re-write of the code snippet you posted.


Empty1 = cont.getActuator("Empty1") #Get the actuator that places Hj1
if z1==1:
     Empty1.setObject("OBHj1")         #setting Hj1 as the object to be placed
     Empty1.instantAddObject()         #Placing Hj1

As you can see, in this case, the list is not used.

setObject() is given the name of the object to be added rather than a reference to the object.

instantAddObject() is called to actually add the object to the visible scene.

The object Hj1 will be added to the scene at the position that it occupies on it’s own hidden layer.

To set the position of Hj1 to the position of an empty you would need to get the the empty object and the Hj1 object from the scene list and then get the empty position and set the Hj1 position.


Empty1 = cont.getActuator("Empty1") #Get the actuator that places Hj1
if z1==1:
     Empty1.setObject("OBHj1")         #setting Hj1 as the object to be placed
     Empty1.instantAddObject()         #Placing Hj1
 
     objList = GameLogic.getCurrentScene().getObjectList()
     Hj1 = objList["OBHj1"]
     empty = objList["OBEmpty1"]
     Hj1.setPosition(empty.getPosition())

Thanks for all the help! I completely misunderstood what the globallist did. Thanks for the extra explaination!

Btw, I was going to go through Byte of Python, I just haven’t begun yet…