Audio & SFX

Music and sound effects are a key piece to any enjoyable game. The Audio class allows you to create and control playback of both ambient and spatial music and sound effects seamlessly within your game.

Playing Ambient Audio

Audio supports a number of features, but let's start with the simplest. Let's say we want to just play some nice ambient music for all of our players. We can do that like so:

startServer(world => {
  // ... Rest of our game setup code
  
  const gameMusic = new Audio({
    uri: 'audio/music/ambience.mp3',
    loop: true, // Loop the music when it ends
    volume: 0.5, // Relative volume 0 to 1
  });
  
  gameMusic.play(world); // Play the music in our world
      
  // ... More game setup code, ordering doesn't matter for Audio
})

Playing Spatial Audio

Oftentimes in games we need to play spatial audio that originates at some point in 3D space of the game, either from a specific coordinate or an entity. In this example, let's play some audio that constantly originates from each player and starts playing when a player joins the game.

startSever(world => {
  // ... Other game code
  
  world.onPlayerJoin = player => {
    const playerEntity = new PlayerEntity({
      player,
      modelUri: 'models/player.gltf', // resolves to assets/models/player.gltf
      modelLoopedAnimations: [ 'idle' ],
      modelScale: 0.5,
    });
    
    const playerSirenAudio = new Audio({
      uri: 'audio/sfx/siren.mp3',
      loop: true, // We could omit loop: true if we want this to be a one-shot, only playing once
      volume: 1, // loud, volume is 0 (ie 0%) to 1 (ie 100%)!
      attachedToEntity: playerEntity,
      // reference distance is the approximate block distance
      // a player can be to start hearing the audio, as they 
      // get closer to the source it'll get louder, up to the
      // volume value.
      referenceDistance: 20,
      // alternatively, we can have this audio spatially emit
      // from a fixed position by removing our attachedToEntity
      // value and instead providing
      // position: { x: 1, y: 5, z: 4 } 
    });
    
    playerSirenAudio.play(world);
  }
  
  // ... Other game code
});

Controlling Playback & Effects

Most audio playback settings and effects can be controlled while Audio is already playing. Effects will automatically be interpolated by the client for smooth transitions between effects. This means you can do interesting things like adjust playback speed, distortion, detune, volume, and more while audio plays.

Here's an example of how we can continuously speed up our audio playback of our game music over time.

startServer(world => {
  // ... Rest of our game setup code
  
  const gameMusic = new Audio({
    uri: 'audio/music/ambience.mp3',
    loop: true, // Loop the music when it ends
    volume: 0.5, // Relative volume 0 to 1
  });
  
  gameMusic.play(world); // Play the music in our world
  
  setInterval(() => {
    gameMusic.setPlaybackRate(gameMusic.playbackRate + 0.1);
  }, 1000); // Every 1 second (1000 milliseconds), increase speed!
      
  // ... More game setup code, ordering doesn't matter for Audio
})

Diving Deeper

The Audio class supports a wide variety of features and control through various exposed properties and methods. If you'd like to learn more, we recommend digging into the Audio API Reference that can be found here.

If there are features that we don't currently support for Audio that you'd like to see added to the HYTOPIA SDK, you can submit a feature request here.

Next Steps

Last updated