engine
engine copied to clipboard
Add 'Destroy' event as a Script Method
Description
Currently, PlayCanvas scripts support the following script methods (https://developer.playcanvas.com/en/user-manual/scripting/anatomy/):
initialize,postInitializeupdate,postUpdateswap
However, it is very common to do some clean-up once a script is destroyed (unbind events, free resources, etc), and the only way to do that is to manually hook up the destroy event:
MyScript.prototype.initialize = function() {
this.on('destroy', this.destroy, this);
};
MyScript.prototype.destroy = function() {
// cleanup
};
I suggest for us to simply add destroy as an optional script method, thus removing the need to manually hook the destroy event.
@Maksims @vkalpias Can you remember why Scripts 2.0 switched destroy from a function to an event?
Event is more generic .. as other object can listened to destroy event of different object - so maybe it was done to have the better (more generic) solution, even though slightly less convenient?
Indeed, it is to be able to know from other places, when something is destroyed. When you have "manager" & "instances" scripts, it was really awkward from manager to know when instance was destroyed. With events it is very simple.
Also, events allow multiple listeners, when prototype method only single one, which in complex projects lead to even more problems.
Same is about enable/disable/state events.
So the rule is: If nobody else, but only the script itself need to know about event, then it is a prototype method. If anybody else would need to know about script event, then it is an event.
If nobody else, but only the script itself need to know about event, then it is a prototype method.
Wait - it sounds like you're saying that, in scripts 2.0, both the event and function work. But I thought only the event worked. This kind of backs that up:
https://github.com/playcanvas/engine/blob/dev/src/framework/components/script/component.js#L121-L127
Just following up as I've literally just run the same issue. It doesn't seem immediately clear from a UX perspective why initialize would be called on the component but destroy would not, even though the event thing makes sense.
I wonder if the destroy event could not be fired on the script component first, before calling it's destroy() if it exists. This would handle the use case where events are needed, but also covers the scenario where someone could reasonably assume that a destroy would be called.
For context; I'm mainly thinking about this in reference to the api for ES Modules.
Just following up as I've literally just run the same issue. It doesn't seem immediately clear from a UX perspective why
initializewould be called on the component butdestroywould not, even though the event thing makes sense.I wonder if the destroy event could not be fired on the script component first, before calling it's
destroy()if it exists. This would handle the use case where events are needed, but also covers the scenario where someone could reasonably assume that a destroy would be called.For context; I'm mainly thinking about this in reference to the api for ES Modules.
Not every script needs to do destroy logic.
Destroy event is usable from outside of a script, that is why it is an event.
Having a method will lead to a confusion, as devs will see a destroy method, then might need to subscribe from other place, they might fire their own destroy event - this will lead to a duplicate destroy event.
There should be least number of branching in learning curve.
Personally I'd love to have a destroy method as a convenience for the users.
Closing this as we do not intend to make further changes to Scripts v2. However, @marklundin, revisit the thread for the Scripts v3 design.