0
\$\begingroup\$

I am encountering an issue where I have a bullet that is destroyed on impact which is cutting off my bullet impact sound effect due to the audio source being destroyed. I like the idea of the sounds being attached to the projectile, but not sure if that is best practice.

I can play the sound from an NPC script, but not sure if that will open up other issues. Is this a better approach since the NPC material is "metal" so I should store all the "Metal hit" sound effects on the NPC?

...vs. having to store all material variations of impact on the projectile?

\$\endgroup\$
0
0
\$\begingroup\$

One way to avoid the audio ceasing when the projectile is destroyed is to call the static method AudioSource.PlayClipAtPoint. This fires a "one-off" sound effect, without being attached to any one specific audio source object.

The downside of this approach is that you can't control the exact falloff or other properties of the sound effect, just its position and volume. If that's a problem though, you can implement your own one-shot-like method. Have a static class or singleton that keeps a pool of audio sources, and on demand configures and deploys one to play a sound with specific settings, then recycles it back to the pool once it's finished playing the sound.

To avoid storing a lot of different material hit sound effects on each and every projectile, you can define a type deriving from ScriptableObject that's something like a "Sound Set" data container. Load up this type with fields/methods to store and select the right sound effect for each material. Then you can create multiple sound sets as assets in your project folder, and share them between many projectiles. Each projectile can hold a single reference to a sound set, and delegate to it the complexity of selecting the right audio clip for the circumstance, keeping your projectile scripts focused on the work of being projectiles.

\$\endgroup\$
7
  • \$\begingroup\$ Noted on the Sound Set Data container. As for the PlayOneShot, I must be missing something because the sound playing or not playing in the code below is based on if I comment out the destroy or not (doesn't play if destroy is called)</br> health.TakeDamage(damageAmount, damageType); sfx.PlayOneShot(RandomClip(), sfxVolume); var newBulletHitFX = Instantiate(bulletHitFX, transform.position, Quaternion.identity); //, this.transform.rotation Destroy(gameObject); \$\endgroup\$ – benbastien Jan 30 at 5:52
  • \$\begingroup\$ Ah whoops, I listed the wrong function name. You want the static method PlayClipAtPoint. I've edited the answer with the corrected name and link to the docs. \$\endgroup\$ – DMGregory Jan 30 at 13:59
  • \$\begingroup\$ Worked in a sense except, now its playing at a ridiculously low volume and the volume parameter doesn't seem to affect it. Pretty sure it has to to with attenuation and 3D sound but I don't want to generate it at the camera audio listener. I found a related thread you were involved with here gamedev.stackexchange.com/questions/168892/… but not sure the solution. \$\endgroup\$ – benbastien Jan 30 at 19:13
  • \$\begingroup\$ You could crank the volume to absurd levels, well above 1. Or Lerp your position to be somewhere between the spawn position and the listener. The solution described at that link is what I mention in the answer above "keep a pool of audio sources, and on demand deploy one to play a sound with specific settings, then recycle it once it's finished' \$\endgroup\$ – DMGregory Jan 30 at 19:30
  • \$\begingroup\$ Ok I will look into that path. Thank you for the guidance. You seem to be everywhere on here. \$\endgroup\$ – benbastien Jan 30 at 20:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.