Sunday, November 20, 2011

Playing Sounds in UnrealScript

SoundCue is a set of instructions that tells the Unreal engine how to play a particular sound. SoundCues are quite flexible and can be created in the UDK SoundCue Editor. Play a SoundCue in UnrealScript is very simple, as can be seen in the code below:
class TestSound1 extends Actor
      placeable;

var SoundCue soundSample; 

event PostBeginPlay()
{
   SetTimer( 3 );    
}
function Timer()
{
   PlaySound( soundSample );
}
defaultproperties
{        
    soundSample = SoundCue'A_Music_GoDown.MusicMix.A_Music_GoDownMixCue'    
}

In the example above I used a SoundCue that represents a music. So at some point I will want to stop this music. Since we use the PlaySound() function then there must be a StopSound() function, right? Wrong, because there is no StopSound() function :(

This restricts the use of the PlaySound() function to small sound effects without loop. In order to use music and sound with loop, we must use the class AudioComponent. The following example creates a AudioComponent that represents a ambient waterfall sound. To test it just put somewhere in the level.
class TestSound2 extends Actor
      placeable;

defaultproperties
{
    Begin Object Class=AudioComponent Name=AudioComp
        SoundCue=A_Ambient_Loops.Water.Waterfall_Medium_02_Cue
        bAutoPlay=true        
    End Object    
    Components.Add( AudioComp )
}

The AudioComponent class has some useful functions:
  • function Play();
  • function Stop();
  • function bool IsPlaying();
  • function FadeIn( float FadeInDuration, float FadeVolumeLevel );
  • function FadeOut( float FadeOutDuration, float FadeVolumeLevel );

As an example, I created a mini game where the player must collect Boots (TestSoundItem class) in the level. A sound plays when the player gets a Boot. This example uses two musics. A game music and a victory music that plays when the player collect all the Boots. Do not forget to set the GameType as TestSoundGameInfo.
class TestSoundGameInfo extends UTGame;

var SoundCue itemSound; 
var AudioComponent gameMusic, victoryMusic;
var int itemCount;

function StartMatch()
{
   local TestSoundItem itemLocal;
   
   Super.StartMatch();
   
   itemCount = 0;
   
   //Check how many Items are on the Level
   foreach AllActors( class'TestSoundItem', itemLocal )
   {
      itemCount++;
   }
      
   gameMusic.Play();      
}

function RemoveItem( TestSoundItem item )
{      
   PlaySound( itemSound );
   item.Destroy();
   itemCount--;
   
   if ( itemCount <= 0 ) 
   {
      Broadcast( self, "You collected all the Items.") ;      
      gameMusic.FadeOut( 2, 0 );
      victoryMusic.FadeIn( 2, 1 );
   }
}
defaultproperties
{        
    itemSound = SoundCue'A_Pickups_Powerups.PowerUps.A_Powerup_JumpBoots_PickupCue'
    
    Begin Object Class=AudioComponent Name=Music01Comp
        SoundCue=A_Music_GoDown.MusicMix.A_Music_GoDownMixCue                
    End Object
    
    gameMusic = Music01Comp        
    
    Begin Object Class=AudioComponent Name=Music02Comp
        SoundCue=A_Music_RomNecris01.MusicSegments.A_Music_RomNecris01_Victory01Cue            
    End Object
        
    victoryMusic = Music02Comp
}

Class that represents the Boots:
class TestSoundItem extends Actor
      placeable;

event Touch(Actor Other, PrimitiveComponent OtherComp, vector HitLocation, vector HitNormal)
{
   local TestSoundGameInfo testSoundGameInfo;    
   
   testSoundGameInfo = TestSoundGameInfo( worldinfo.game );
   
   if( testSoundGameInfo != None)
   {    
    if( Pawn(Other) != None && Pawn(Other).controller.bIsPlayer )
    {               
        testSoundGameInfo.RemoveItem( self );      
    }
   }
}     
defaultproperties
{        
    bCollideActors=true    
    bBlockActors=false
    
    Begin Object Class=CylinderComponent Name=CylinderComp
        CollisionRadius=20
        CollisionHeight=28
        CollideActors=true        
        BlockActors=false
    End Object    
    Components.Add( CylinderComp )
    CollisionComponent=CylinderComp    
        
    Begin Object Class=DynamicLightEnvironmentComponent Name=LightEnvironmentComp
        bEnabled = true
    End Object    
    Components.add( LightEnvironmentComp )
    
    Begin Object Class=StaticMeshComponent Name=StaticMeshComp
        StaticMesh = Pickups.JumpBoots.Mesh.S_UN_Pickups_Jumpboots002    
        LightEnvironment = LightEnvironmentComp
        Scale = 2
    End Object    
    Components.add( StaticMeshComp )    
}     


For more information about Sounds:
Audio System