Audio effects for Enemies
Objective: Add audio effects to enemies for attacking, walking and dying.
First consider how many audio sources are needed. Each enemy should have a unique audio source to allow foot steps to be heard from a direction and distance from the player. The audio listener is on the Main Camera that moves with the Player. Each enemy is structured in the hierarchy as shown below for the skeleton. Skeleton organizes way points and the actual Skeleton_Enemy, which contains the scripts and physics components.
Add an Audio source to the Skeleton_Enemy. The audio clip is assigned through code, so leave it as none. Adjust the spatial blend to 3D which allows the use of volume rolloff. Change the rolloff to linear, and adjust the max distance to 25. This allows near enemies to be heard while distant enemies are can be hear to the right or left provided they are not too far away.
All enemies currently use an abstract class Enemy, thus introducing audio elements into this script allows individual instances on multiple different enemies. Two bools are used to track the whether the enemy is playing an audio clip for _attackPlay or _movePlay.
Add an audio source variable _audio, and assign it in the Init() method using _audio = GetComponent<AudioSource>(). Init() is called within void Start(). The audio clips for _moveClip, _deathClip and _attackClip are assigned using serialize field for each enemy instance, Skeleton is exemplified below. Each enemy instance has its own audio clips assigned. The clips for a spider differ from those of the moss giant or skeleton.
The AttackAudio() method is used to assign and turn on the audio clip and sets it to loop while the monster is InCombat. The bool _attackPlaying is used to avoid restarting the audio unnecessarily. On arrival at a way point the IdleAudio() method stops the audio and resets the Booleans and turns off looping.
The AttackAudio() is called when the enemy is in range of the Player and begins the attack animation by setting the InCombat bool parameter to true. If the Player is not in range the StopAttackAudio() method stops the audio clip after the InCombat parameter is used to halt Attack animation, see below.
A similar approach is taken for the MoveAudio() method, which is used to assign and turn on the audio clip and set the clip to loop while the monster walks between way points. The bool _movePlaying is used to avoid restarting audio unnecessarily. On arrival at a way point the IdleAudio() method stops the audio and resets the Booleans and turns off looping.
The MoveAudio() is called as shown below after the enemy is told to MoveToward the target way point.
The IdleAudio() is called upon arrival at the target way point after the Idle animation is triggered.
DeathAudio() method is the easiest to implement because it does not need to be looped or stopped. Once again the currently playing _audio is stopped, a new clip is assigned and played. The other variables are set to false as they are no longer active. The audio will end after completion.
The DeathAudio() is called from the Damage() method, a part of the IDamagable interface, within either the Skeleton, MossGiant or Spider scripts. If the Health is ≤ 0 then the DeathAudio() is executed.
A key learning is to use the spatial blend 3D audio, even in a 2D game, along with rolloff to avoid hearing all the enemies on the map at once. If you enable audio source gizmos their max distance can be visualized in the scene view.
This article uses assets from GameDevHQ Filebase but can also be found on the Unity Asset Store as Dungeon Escape.