Correct syntax for sending message

I have a ray sensor and I need to sens a message to the object it hits with python, but this doesn’t appear to work:

own.sendMessage("subject", "empty body", ray.hitObject)

What’s the correct syntax in this case?

Hello! I need this solvement very quick, otherwise I’m stuck.

it looks like it should be bge.logic.sendMessage, not own.sendMessage:

Doesn’t change much. I use ray.hitObject as it is object added from inactive layer. Hm… May it matter?

Please, I can’t progress my game without this. I am making a quick game to publish in Game Jolt(it will be first game that I will finish) and I need to make it as quick as possible, that’s why I need help.

bge.sendMessage( "subject", "body", ray.hitObject)

Should be the correct syntax.
Are you sure that your ray is registering a hitObject? What are you using for the hitObject to receive the message?

How is your script ‘not working’? What is it supposed to do, and what is it currently doing?

It is supposed to send message to a hitbox of enemy so that the hitbox, after recieving message, removes some health from enemy.

bge.sendMessage( “subject”, “body”,
the right syntax should be this (all strings)

but it send a message to all object with the same name

better use a bullet as messenger, ie:

if ray.positive:
   hit = ray.hitObject
   bullet = scene.addObject("Bullet", hit, 1)

I add bullet - what’s next? However, it’d be better if sendMessage() would use KX_GameObject as 3rd attribute instead of string/
So - what should I do with the bullet? Is it like bullet.parent … What’s next? Maybe do something that gives a positive pulse for controller in the bullet’s parent so that no messages needed to remove health of enemy?

the enemy can check for -> collision [BULLET]

if sensors["CollisionBullet"].positive:
    own["health"] -= ..

the bullet can be a obj static ghost with a property “BULLET”

However, it’d be better if sendMessage() would use KX_GameObject as 3rd attribute instead of string/

i think the same but maybe can require a completely different implementation with some risk about performances if not done well

for example, this (not tested) should be fast , but work ONLY with gameobject as key:
afaik is the key the potential bottleneck


import bge

_MESSAGES = [defaultdict(list), defaultdict(list)]

def send_to(obj, subject=""):
	subject = str(subject)

def get_messages(obj):
	return _MESSAGES[0][obj]

def update():
	_MESSAGES[1] = defaultdict(list)


I posted the thread about physics reducing FPS in this game so I can say - checking for collision isn’t the best. Even more - static object doesn’t collide static object.

own.sendMessage("subject", "empty body", ray.hitObject)

I’m unsure but I think you could try something like below instead


I remember Monster used to advice us to just broadcast messages to everything and let the receivers decide what to do themselves, so your hitboxes should contain message sensor(logic brick) that verify the message(“subject”) and act on it accordingly, it might be a little bit tiresome to do this when you have a lot of items but that’s how I normally do it, hope it helps

If you already have a hit object, then just set a property directly on that hit object.

on the bullet:

ray = ####
hit_object  = ray[0]
if hit_object:
    hit_object['health'] -= own['power']

on the hit object:

if own['health'] <= 0:
    own['dead'] = True

elif own['health'] != own['old_health']:
    own['been_hit'] = True
    own['old_health'] = own['health']

You don’t need to send a message, having a message sensor checking every turn whether a message has been received is only slightly faster than having a python script checking health every turn. You can even set it to check only every 4 or 5 tics if you want to preserve speed. It won’t be noticeable.

This way you can record if the object has been hit, or if it has been killed. You could even check if new health is higher than old health and do a healing animation.

@guramax but if I send message using that method, all hitboxes will recieve it.

@Smoking_mirror: Hitboxes are parented to empties which are parented to bones of armature which is parented to collider of enemy that contains health property. This method won’t work.

It’s no problem to check your hitboxes to see if they have taken damage. Just make a list of them at start-up and then iterate through the list each turn.

### on the bullet
if hit_ray[0]:
    hit_ray[0]['damage'] += own['power']

### on the enemy 
if "ini" not in own:
    ### get all my hitboxes at startup, 
    ### give each hitbox a "hitbox" property (bool = True) and a "damage" property (int = 0)

    hitboxes = [ob for ob in own.childrenRecursive if ob.get("hitbox")]
    own['ini'] = True
### check my hitboxes for damage
for box in own['hitboxes']:
    if box['damage'] > 0:
        own['health'] -= box['damage']
        box['damage'] = 0

The agent will be checking his hitboxes to see if they have received any damage, if they have, the damage is picked up by the agent and the damage is reset to zero so it won’t keep repeating the same damage.

You can also give the hit boxes a special location property for special hit effects:

if box['location'] == "head":
    own['headshot'] = True
if own['headshot']:
    own['dead'] = True

I did this on my old battletech game to take in to account different armor values on different limbs, as well as weapon locations having chance of being damaged.

OK! I will try this.

In first code:

if hit[0]:

There should be : at the end, right? Also, can I use this on the gun script and use KX_GameObject bullet for accessing property?

### on the bullet
if hit_ray[0]:
    hit_ray[0]['damage'] += own['power']

Yes and hit_ray[0] is the object that got hit.
What kind of ray are you using? A sensor or a python ray? I think with sensors it’s ray.hitObject to get the object hit by the ray. Python rays return a list, the first entry being the hit object.

I use sensor. For now the hitboxes gets damage.

It was pointed out already, but I feel it should be reiterated as it’s the heart of the thread’s title; the hitObject instance variable is of the KX_GameObject data type, not a string. sendMessage requires all passed parameters to be strings and will fail with anything else.

That being said… maybe cast to string with str()?

own.sendMessage("subject", "empty body", str(ray.hitObject))

No idea if (1) this will even work, (2) it’s going to overload the message with data, and (3) if you can ever get it back to what it was… but at least we can rest in the solace of knowing that sendMessage will be getting a string.

Edit: I just tried, and with just “ray.hitObject” as the “To” parameter sendMessage fails citing “TypeError” as expected. However, with str(ray.hitObject) it worked without complaints. So, indeed, this can work to correct the syntax. Unfortunately, it does not look to pass that much interesting data, so cannot work as a hack to send KX_GameObject type data over a message. (which, admittedly, is probably for the best)