when playing a sound, as I understand it, Defold notifies the initiating gameobject when the playing is done by a) calling an optional callback funtion and b) sending a “sound_done” message:
sound.play( url, props, function( self, message_id, message, sender )
-- sound has ended.... do things
end )
Often, I have the case that an initiating object does not need this information. In fact, when I have e.g. a bullet gameobject initiating a sound on impacting its target, the bullet has already been deleted when the sound is done playing. In that case, I get an error message which I would like to avoid:
ERROR:GAMEOBJECT: Instance '/instance12' could not be found when dispatching message 'sound_done' sent from playground:/instance12#sound
I would have thought that just the fact of providing a callback function would already prevent that message sending? After all, such a function will always take care of any action required upon the sound ending and an additional message being passed seems useless - but apparently, the “sound_done” is always sent?
Is there a way when playing sounds to prevent Defold from sending “sound_done” when I do not need / want it?
The callback function is still tied to a script+gameobject.
During setup of the callback, we get the gameobject instance but if it’s been deleted, then it’s not much to do.
I do think that the error message is not very useful in this case, and perhaps we could check for this circumstance.
Ok, yes, then my problem is indeed that as the gameobject no longer lives, neither does the callback function.
Well, I would be happy if you decided to check for the existence of the gameobject before sending the “sound_done” and prevented the error message. There is actually nothing the game code can do to remedy the “error” and at least to me, it is just a common (edge) case.
One way or the other - thanks for explaining to both of you!
yes, that is the problem: I could just play the sound without providing a callback function and that would actually work. Without a callback, no “sound_done” message would be sent, no error message generated.
However, it is a bit more complicated:
To play sounds, I use a library that takes care of other tasks such as orchestrating and ommitting sound instances when (too) many want to get played at the same time. That module always provides its own callback to sound.play() to do its housekeeping. So even when, as in this bullet/explosion example, the bullet does not need a callback function to execute custom game code, the library still does, and so produces an error message.
One solution is to not play the sound from a script attached to a short lived game object. Having a central sound manager which plays sounds is a pretty good design. Also, if the only purpose of the bullet script was to play sounds then you’d now have the opportunity to remove it if you move the responsibility to a central sound manager.
A central sound manager is what we use in our games. It has many benefits. For example, it makes it easier to implement features such as sound gating / not playing sound samples too often.