Can't change object properties with Python

What’s wrong with this code?


    
    c = GameLogic.getCurrentController()
    a = c.owner.actuators[0];

    a.instantAddObject();
    bike = a.objectLastCreated;
    
    #let everyone know
    GameLogic.number_of_baddies +=1;
    
    #setup:
    bike['range'] = 30 + 20*(GameLogic.getRandomFloat() -0.5)
    bike['speed'] = 20 + 5 * GameLogic.kills +  (10 * (GameLogic.getRandomFloat()-0.5) );
    bike['evade_speed'] = 100 + 50 * GameLogic.kills +  (200 * (GameLogic.getRandomFloat()-0.5) );
    bike['attack_freq'] = 0.9 + (GameLogic.getRandomFloat()-0.5)/10.0;
    bike['HP'] = 1;

a is an Add Object brick connected to the script. The object to add is already entered in the brick.

Thing is, this script works for one object but not another; When I later try to use the speed, range, etc. variables I get this old error:

KeyError: 'value = gameOb[key]: KX_GameObject, key "speed" does not exist'

The objects are for all intents and purposes identical (same code, different mesh object). What could possibly be causing this?

1 Like

I thought instantAddObject only returned the object specified in the .object attribute but didn’t really do anything. Even if it did, AFAIK, the actuator would only add the object in the next tick. Either way it wouldn’t work.

You could just use the scene.addObject(), that one is I’ve used and I’m sure it works. You’d just do it like:
bike = scene.addObject(“bike”, own)
text[“speed”] = 0

I use this:

cont = GameLogic.getCurrentController()
own = cont.owner

scene = GameLogic.getCurrentScene()
(Name) = scene.objects["OBObject Name Here"]

vibrunazo: well, I replaced those two lines with what you suggest, and now have:


    #a.instantAddObject();
    #bike = a.objectLastCreated;
    scn = GameLogic.getCurrentScene();
    bike = scn.addObject( 'bike', hangar );

I get exactly the same functionality as before: the objects are created okay, but none of the properties are assigned to them.

moffboffjoe: I don’t understand what you mean. Your code works only if I am trying to find an object that already exists, and that I know the name of.

Your “Bike” object needs to have whatever propertys the script is assigning. Try using the object.has_key(key) statement.

As I see the problem is not this script. I tried and it was fine.

You wrote you get the error somewhere else. Please show us the script where the error occurs.

I assume that you do not access the same object, when you get this error.
You have to keep in mind that all added objects will have the same name. If you perform getCurrentScene().objects[“OBBike”] you will get just any of the objects not all.

Yes, the error comes from somewhere else. But, it’s only this:


Python script error from controller "ai#CONTR#1":
Traceback (most recent call last):
  File "/home/tog/Desktop/iter/ai.py", line 30, in keep_range
    fact = ship['speed'];
KeyError: 'value = gameOb[key]: KX_GameObject, key "speed" does not exist'


As you can see, all I was doing was assigning the property to another variable. I can’t imagine anything that could go wrong there. But, for completeness, here’s the function it came from:


def keep_range():
    c= GameLogic.getCurrentController()
    ship = c.owner;
    
    ship['target'] = GameLogic.player;
    if ship['target'] == None or ship['target'].invalid: return;
    
    fact = ship['speed'];
        
    vect = ship.getVectTo(ship['target']);
    if  vect[0] > ship['range']:
        ship.applyForce( [vect[1][0]*fact, vect[1][1]*fact, vect[1][2]*fact ] ,0);
    elif vect[0] < ship['range']:
        
        ship.applyForce( [-vect[1][0]*fact, -vect[1][1]*fact, -vect[1][2]*fact ]  ,0);
        

As for finding the correct object, it shouldn’t be a problem; they’re all created via that first script, and are always ‘found’ via GameLogic.getCurrentController().owner or [collision sensor].hitObject. I haven’t gone via scene.objects[‘name’] anywhere.

Also to note: if I create all those properties beforehand (in the Logic panel) and give them all fixed values, this works fine. So it really does seem as if the bottom five lines of that script are not running at all. (Of course I know they are - I put a print “chk”; statement after them.)

You could add a check to the script that prints information on the object if the property is not there. That might help you to see which object it is. With this information you might discover why it does not have the properties you expect.

Following code prints all properties of the object when the expected property is not there:

 
if not ship.has_key('speed'):
    print "Ship = ",ship.name,"with",
    for property in ship.[getPropertyNames](http://www.blender.org/documentation/249PythonDoc/GE/GameTypes.KX_GameObject-class.html#getPropertyNames)():
        print property,"=",ship[property],
    print "is missing property 'speed'"

or
You add following code after you added the new object (and assigned the properties). With this you can see if you have an object without the properties.


for obj in GameLogic.getCurrentScene().objects[:]: 
 if obj.name==a.object.name \
 and not obj.has_key('speed'): 
     print "Object = ",obj.name,"with",
     for property in obj.getPropertyNames(): 
         print property,"=",obj[property], 
     print "is missing property 'speed'"

An alternative way would be to give the “Master” a script to set the properties by it’s own. I can’t see any dependency between the emitter object (the one with the addObjectActuator) and the added Objects so that should be fine.

I hope it helps.

PS: Could it be that you activated the add object actuator? Added Objects from the activation wouldn’t get the properties by the script.