Sending events to many spawned clones?

What’s the best way to send events to many identical clones? Are events a better approach than running a script function on the entity?

I can’t quite tell if I can send and event ‘at’ a specific entity/script?

Is it valid to add a whole UUID as a prefix to an event name?

(Goal is to have external data, that I’m bringing in from a parent react app set parameters on many clones - multiplayer)

Bruce

An entity on itself (or its clone) will not be able to catch an event, unless it has a script component with script that listens for that event attached to it. If your clones have a script attached, then it is fine to send an event that they can listen upon, e.g.

this.app.fire('action', myData, someOtherData, etc);

Instead of many attributes, you can also pass a single object, as an attribute to the event, like:

var data = {
  key: 'clone1',
  type: 'jump',
  group: 'blue'
};
this.app.fire('action', data);

Then all your clones would listen for event "action" and act, based on the arguments you pass.

Clone.prototype.initialize = function() {
    this.key = 'clone1';
    this.app.on('action', this.onAction, this);
};
Clone.prototype.onAction = function(arg1, arg2, arg3, etc) {
    // arg1.key === 'clone1'
   if (arg1.key === this.key) { 
       // do something
   }
};

The idea is that you send an event, that all clones will hear, but only selected ones or even a single one would act upon. You would need to somehow differentiate cloned entities, by giving them a unique ID, or adding a unique tag, color or name, etc.

Edit:
Another option would be that you would have a single entity, which knows about all the clones out there in your scene. That entity would be the only listener for the event, and would be the only one that has a script. When it catches the event, it would read from that event which clone it is addressed to and then would simply do something with that clone, like move it, hide, scale, and so on. Clones would be simple entities without scripts then.

3 Likes

Just to add on what @LeXXik nicely explained, you can add/listen to events to pc.Entity instances, or any other object, by using the following method to inherit that functionality:

pc.events.attach(this.entity);

Then you can do this:

this.entity.fire("myEventName");

And in the same way for adding listeners with .on() etc.

2 Likes

Thank you for the input, @Leonidas! What would be the difference or when one would prefer to use this method over this.app.on?

1 Like

I use it quite often to target event listeners on an entity when it has multiple scripts attached.

So I can target a single entity without having to do redundant checks on all entities listening, if they are the one.

2 Likes

I also send messages on the entity for different scripts isntances on it to communicate with each other.

2 Likes

Ah ha, thanks guys. Lexxik, that was about what I thought but Leonidas, thanks, that may be what I was asking, but I can’t tell which this and which entity makes which call?

So if I have a manager script called manager and then children called A, B, C, D, E, and wanted to send the same event to only one, would it be:

pc.events.attach(this.entity);

And then in the manager:

const myObject = ABCDorE (criteria);
myObject.fire(event);

In which case how do I set the handler in the objects? As if it’s a global event with this.app.on?

Do you want to send an event to a specific entity or to every entity? Not too clear on this?

I’m spawning up to a hundred of so avatars to represent multiple players. When they move (or other actions) I get a message with ID and activity. Then I create a clone if needed and set the avatar’s position and appearance.

So I get a message with ID and want to look up the right entity and set that (I just asked another questions about GUIDs), i.e. send a message to one entity specifically (they all will have the same script to handle the event)

In this case I would either have some central controller that maps a UUID to an entity reference or target the entity via a unique event name that includes the UUID on the app object (thus making it a central message bus). Eg player:<UUID>:move

That second option I mentioned in original question - whether squeezing a UUID into the message was fine.Is that more efficient than calling a script function in the entity?

For your first option, I’m pretty sure I can get from id to entity, but looking to know how to send the event to that one entity only - how does the entity register for the events?

Ok, this is making my head hurt a bit, but am I right in saying you don’t send an event to an entity, an entity listens to another entity for their messages?

So in my situation, to use events, I must encode the ID in there so all the other mostly identical clones don’t respond? Any guess on efficiency between everyone getting it and some ignoring it versus adding ID to the event name? (or just calling a function manually)?

Every PlayCanvas object (entity, component, application, system etc) all have an instance of the same messaging class that can fire events and register listeners to.

Off the top of my head, when an event has a listener registered to it, it’s stored in a map so has O(1) when the event is fired.

In the latter example where I suggested sending an event with the GUID as part of the event name, that would be fired on the application object. Every script instance has a reference to the application object which makes it easy to fire and listen for events on.

Thanks. Trying all that.