Very Quick Question About Message Actuators

What does the “Property” option under “Body” do in a message actuator?

It’s used to send a property to the message sensor receiving it.
http://www.tutorialsforblender3d.com/GameDoc/LogicBricks/Actuator_10.html

Though you can only retrieve it (in the sensor) if you use a python script.
http://www.tutorialsforblender3d.com/GameDoc/LogicBricks/Sensors_11.html


Please have a look at the BGE Guide to Messages incl. Healthbar tutorial. It shows you how you can use it ;).

Ok, I think I’m starting to understand. So, the message actuator won’t actually send the specified property, but it will send the value of the specified property.

@Linkxgl: With retrieving the property value through Python, I’m guessing it’s just taking the value that’s sent and applying it to a property that is already on the receiving object. Is this correct?

@Monster: Wow, that guide is an amazing resource for anything you could need to do with messages! I’m really starting to realize just how important they are, especially since they are the only way to send information across scenes. This guide will definitely be something that I will be looking back on often. :smiley:

Ok, I’ve gone back to my project, and I have another question: how would you access the property through python? It appears, from looking through the API, that you have to access it in some way through the list of bodies, but I am unsure of how to get the information out of this list and into a format that I can use to change a property. Also, I apologize if this is any of the resources that either of you have directed me to, and I just missed it :slight_smile:

you correctly discoverred that the message body carries the value of the property. To be more specific it contains a copy of the string representation of the value.

You retrieve this value from the bodies of the message sensor. You can use the S2A (see my libraries) to grap it fom there. The examples from the above thread show you how go do that.

Well… I rarely ever use messages. First make sure that using a message is the only way of achieving your wanted result.
I didn’t know how to do this myself, so I looked at this API reference for the BGE:
http://www.tutorialsforblender3d.com/GameFunctions/ClassIndex_1.html
Under this:
Message Sensor Variables

Basically, when you send a message using an actuator you can give the message many bodies/properties (like attachments in e-mails). So instead of receiving individual variables, the message sensor puts all the bodies it has received into one variable called a list.

To access this list you need to have a message actuator connected to a python controller that accesses this list.
So something basic, like this, could work:


from bge import logic

def main(cont):
     sensor = cont.sensors['message_sensor'] #Accesses message sensor

     props = sensor.bodies #Accesses the list of bodies

     first_prop = props[0] #Accesses the first body in the list of bodies


Edit 2: And as Monster said, it gets received as a string. You can convert a string to an integer (if it’s a number) using the “int” function built in with python, and you can then use it how ever you want.
Example: int(number in from of string)

Though I’m not entirely sure what you mean by changing the value of the property.

Edit: Monster beat me to it with his example thread already haha :stuck_out_tongue:

Ok, here is what I’ve come up with:


 
import bge
 
 
cont = bge.logic.getCurrentController()
message = 
cont.sensors['Message']
properties = message.bodies
first_prop = 
properties[0]
 
 
def main():
 
    if first_prop == 
'red':
        scene.addObject('red_ring', 
'spawn')
 
    if 
first_prop == 'blue':
 
scene.addObject('blue_ring,' 
'spawn')
 
main()

The goal is that depending on which property my object receives, I want it to add a certain ring (this is really just a test so that I can figure out how these messages work). As far as I can tell, it should be working, but when I run the script I get an error that says “CList[i] Python ListIndex out of range in CValueList.” What’s going wrong?

@Linkxgl: What I meant by changing the value of the property was that I had at first thought that I would need to take the property value that is in the body of the message and apply it to another property. However, I now see that this isn’t necessary, so I don’t intend to do it.

@Monster:
Also, I saw your S2A, and I think that if I can’t get this figured out, I will just use that. The only reason I’m still trying this is so that I can learn more about logic bricks and Python. I want it to work correctly, but I also want to fully be able to understand how it works :wink:

I recommend to switch to module mode first.

There are multiple options. First analyze your requirements. Then try to find solutions.

Requirements:
A) transfer the value from an object’s property to the property of another object
B) use the value of an property to add a specific object.

Solutions:
A) as discussed earlier.
You can use the MessageActuator for sending a message and a MessageSensor for receiving, but you need Python to read the message content. As said, you can use the S2A.py which is just doing that.
Simple example code:


def firstBodyToMyProp(cont):
  bodies = cont.sensors[0].bodies # does not deal with other sensors!
  if not bodies:
    return
  body = bodies[0] # only deals with the first message
  cont.owner["myProp"] = body # the type depends on the type of property as defined in GUI otherwise String

(The S2A expects a property actuator. So you can defined your property at the actuator)

B)This has nothing to do with A)
You can do that even with logic bricks:
PropertySensor myProp equals “red” --> … --> AddObjectActuator “Red” + PropertyActuator “myProp” assign “”
PropertySensor myProp equals “blue” --> … --> AddObjectActuator “Blue” + PropertyActuator “myProp” assign “”

Or via Python

requires a PropertyChangeSensor:


for selectByPropValue(cont):
  value = retrieveValue(cont)
  dealWithValue(cont, value) # see below

def retrieveValue(cont):
  sensor = cont.sensors[0] # ignores other sensors
  if not sensor.positive:
    return None
  value = cont.owner[ sensor.propName ]
  return value

Examples to deal with the value:
a)


def dealWithValue(cont):
  '''
  Activates the actuator with the name of the value
  Requires actuators with names matching the expected property values
  '''
  if not value:
    return
  cont.activate(value) #will fail if the value does not match an actuator name

b)


import bge 

def dealWithValue(cont):
  '''
  Adds objects with the name of the value
  Requires game objects with names matching the expected property values
  '''
  if not value:
    return
  scene = bge.logic.getCurrentScene()
  scene.addObject( value, cont.owner ) #will fail if the value does not match

c)


VALUE_TO_OBJ_NAMES = {
 "red":"Red"
,"green":"Green"
}
def dealWithValue(cont):
  '''
  Adds objects according to the value
  '''
  if not value:
    return
  scene = bge.logic.getCurrentScene()
  objectName = VALUE_TO_OBJ_NAMES (value) # will fail if value is not matched
  scene.addObject( objectName , cont.owner ) #will fail if the name does not match an existing game object

And yes, you can put all code into one code block. You can even skip to place the body value in a property and directly use the body value to add the objects. But - as far I understood you - is a requirement for you to see the property.

Ok, I am very embarrassed now. :o I just went back over my test file, and i noticed that I had not named the objects that I wanted to add “red_ring” and “blue_ring!” After making these changes, I’ve found that it works perfectly! Thank you Monster and Linkxgl for your help with this problem.

Is there a way to use this transfer mechanic via the message actuator and python to just transfer values (integer-type property)? So for instance, a cube has a property (prop) with a value of 10, and wanna transfer that property value to another Cube with same property name (prop) so that the second Cube’s value is identical to the first?

Not sure about the python stuff, but I believe for that you could use the copy property type in the property actuator.

Right, i’m familiar with that, it’s very useful. The only problem is that I need a way to “paste” properties, if that makes sense. So basically I need a singular object to both copy properties (using the copy property function in the logic bricks) and send property information as well. the reason why I can’t use the copy property function on the end of the reciever instead of the sender is because if there are multiple objects doing this (Cube, Cube.001, Cube.002, etc.) there’s no way for the copy property logic actuator to know who to send it to… that’s my current dilemma.

you can access game objects in the scene by using obj = scene.objects["objname"] and you can access properties by using read = obj["prop"] and obj["prop"] = write where read and write are the info.

last i checked, scenes can have “properties” too, which everyone can access. scene["prop"]. correct me if im wrong…