So I'm making an RTS type game, just for practice and exercise, but when I send someone somewhere, I want them to know when they need to stop. I decided this could be done by having the marker that they go to send them a message when they're near it. How can I make the message send only to the guys that are within, say, 3BU from it?
It is just an Always sensor, set to True level triggering; and a Near sensor. Those two are plugged in to the python controller, which will activate the message actuator. The property in the Near sensor is not needed, that is only to limit what objects get the message.
The script will send a message to every object that is near (3 units or closer) the marker.
import bge cont = bge.logic.getCurrentController() list = cont.sensors['Near'].hitObjectList if cont.sensors['Near'].triggered: message = cont.actuators['Message'] for obj in list: message.propName = obj.name cont.activate(message)
- The script gets all the objects that are near the marker and stores it as the
listvariable (line 5).
- The if statement works like this, when anything is near the marker, the near sensor is triggered, thus it is True.
It then loops through the list of objects that are near, and sets the message actuator's "To:" field to one of the objects. (
message.propName = obj.name)
- The last line still part of the loop, activates the actuator - sends the message.
I do not recommend to use the "To:" parameter at all. It creates a direct dependency to a single object.
One of the biggest advantages of messages is that you do not get such a dependency. Beside of that you couple the actuator to a single object which is contradictory to your requirement to interact with multiple objects.
I suggest to use a different architecture.
- Identify the objects within range
- Set according properties of the identified objects.
- Objects with that property sense if the property value changed
1) Can be done with a near sensor. It serves several purposes. You set up the detection range, you set up the property name (A) and it senses the objects within that range.
2) Can be done with a Python controller. Due to its dynamic nature there are no sufficient build-in logic bricks. Python controllers do not have additional configuration parameters. So we can use a little trick to setup the value we want to send without hard-coding it. We use a connected message actuator and setup the value of the subject field (B) [The actuator will not be activated]. This looks pretty similar to your proposed idea.
The code retrieves the found objects and sets the property value for each of them:
import bge def subjectToNotification(): hitObjects = getHitObjects() if not hitObjects: return property = getPropertyName() value = getPropertyValue() for hitObject in hitObjects: hitObject[property] = value
While this describes the basic operation we want to achieve, it misses some details. You can use your own flexible implementations of the details. Just in case you have no plan, here is a simple implementation to be appended to notifier.py:
def getHitObjects(): sensors = bge.logic.getCurrentController().sensors sensor = sensors return sensor.hitObjectList def getPropertyName(): # (A) and (C) sensors = bge.logic.getCurrentController().sensors sensor = sensors return sensor.propName def getPropertyValue(): # (B) actuators = bge.logic.getCurrentController().actuators actuator = actuators return actuator.subject
I hope it helps
PS: With the above implementation (A) and (C) should have the same property name.