How Game Engines Handle Loop Points in Audio Files

A music file that loops perfectly in one engine can click, gap, or ignore your markers completely in the next. I write music for games, and I kept running into this from the delivery side: the same WAV, authored the same way, behaving differently everywhere it landed.

So here’s what I found across eight engines, including one thing I had wrong until a reader corrected me.

These are two separate problems

They get conflated constantly, and almost every discussion only covers the first one:

  1. Does the engine read the loop points you embedded in the file?
  2. Even when it does, what happens to the reverb tail at the wrap?

The second is the harder problem, and no loop point fixes it.

Part one: does the engine read your loop points?

First, where loop points actually live. In a WAV they sit in a chunk called smpl, named that because it was originally for hardware samplers, and it’s been in the spec since the 1990s. Cue markers are separate, in a cue chunk. In OGG, FLAC and Opus there’s no specification for loops at all, so the convention is LOOPSTART and LOOPLENGTH in the Vorbis comments. A convention that caught on, not a standard.

Most DAWs will write these. The catch is that writing them is standard and reading them isn’t, so your metadata is usually sitting in the file, perfectly correct, and the engine simply never looks.

Godot

Reads the WAV smpl chunk natively, and in current Godot the Import dock’s Loop Mode already defaults to Detect From WAV, so a marked WAV loops with nothing to set. Easily the most straightforward of the group. I wrote this one up in full, including the dropdown choice that silently discards your markers and where OGG falls short: Godot Reads WAV Loop Points Out of the Box. Almost No Tutorial Mentions It.

Unity, which is the one I got wrong

I originally wrote that Unity ignores embedded loop points. That’s what most sources say, and it’s wrong.

Unity does read the smpl chunk. With looping enabled, playback starts at the beginning of the file and then wraps inside the loop region rather than returning to zero. Only the first loop in the chunk is used.

Two things explain why it keeps getting reported as unsupported. It’s undocumented: nothing in the AudioSource documentation mentions it. And it’s fragile: the default Vorbis import re-encodes the audio, and the loop points shift or vanish. You need WAV sources with Compression Format set to PCM, or Load Type set to Decompress On Load. Test with default import settings and you’ll conclude the feature doesn’t exist, which is exactly what I did.

My thanks to the commenter on r/Unity3D who pushed back on this. The corrected version is more useful than what I originally published.

Unreal Engine

Won’t read smpl loop points no matter how you author them. It does read cue markers, sample-accurately, which makes cue markers the practical way to carry a musical grid into a MetaSound.

RPG Maker MV and MZ

Reads LOOPSTART and LOOPLENGTH tags in OGG. This is where that convention comes from, and it’s the reason those tag names are worth knowing even if you never touch RPG Maker. I wrote that one up on its own, including why the native loop cannot carry a reverb tail and what to do about it: RPG Maker Loops Music Seamlessly Without a Plugin.

FMOD Studio and Wwise

Both handle looping inside their own project rather than from the file. In Wwise, a looping Sound SFX will honor an embedded smpl loop, but music uses Entry and Exit cues on a Music Segment instead. In FMOD, you place a loop region on the event timeline.

GameMaker and Adventure Game Studio

Neither reads embedded loop points. AGS loops the whole clip through its Repeat setting, so it needs a file whose start and end already join cleanly.

Part two: the reverb tail, which is the real problem

Now assume your loop points are sample-perfect and the engine honors them. If your music has any reverb, delay or natural decay, you’ll still hear the seam.

The reason is simple once you see it. At the loop end, the sound of the last bar is still ringing. It’s supposed to keep ringing into whatever comes next. But the playhead jumps back to the loop start, that decay has nowhere to go, and it’s cut dead, replaced by the dry attack of the loop’s first sample. The room goes silent for an instant, and your ear reads that as a gap even though there’s no gap in the samples at all.

This isn’t a bug, and it isn’t a loop-point problem. It’s a structural consequence of one playback position wrapping.

If you would rather hear it than read it: Hear the Loop plays a hard cut against a tail overlap right in your browser, on your own music if you like.

Part three: the two ways to fix it, and what each costs

Two voices

Play the loop on one voice, and when it reaches the loop end, start a second voice at the loop start while the first keeps playing past the end. For a second or two you have two copies of the track sounding at different positions, and the old pass’s tail rings over the new pass’s opening. Then you alternate.

Support varies by engine:

  • Wwise does it natively. A Music Segment plays its post-exit audio over the restart, on by default.
  • FMOD does it with a transition timeline on the loop region, with the tail as an async instrument. FMOD’s own QA has described this setup as “not very discoverable,” which is fair.
  • Unreal builds it from two Wave Players handing off at the loop point inside a MetaSound.
  • Unity, Godot and the web have no native support, so you schedule it in code.

The cost is a second voice, and in the code engines, actual code.

Fold the tail into the head

Take the decay that would have rung past the loop end, and mix it into the opening of the file. Now a plain looping playback is seamless with nothing running at playback time.

The cost is subtler and worth understanding: the first pass is a small lie. The head now contains the decay of a pass that never played, so the very first time the track starts, you hear a reverb tail coming from nothing. On dense material nobody will ever notice. On a sparse opening, or when an intro section feeds into the loop, it’s audible.

Which to use

Two voices when the engine can schedule audio accurately, because every tail you hear was genuinely produced by a pass that played. The folded tail for one-voice engines that just play a file and loop it, like RPG Maker, GameMaker and AGS, where it’s the only option that preserves a tail at all.

Part four: the scheduling detail that catches people

If you’re writing the two-voice version yourself in Unity, two things matter more than they look.

Use the DSP clock. Schedule against AudioSettings.dspTime with AudioSource.PlayScheduled, never Time.time, a coroutine, or anything tied to the frame rate. The DSP clock is sample-accurate and won’t drift over a long session. If your handoff moves when the frame rate changes, that’s the bug.

Call early, but schedule the exact boundary. Make the PlayScheduled call about a second ahead of the deadline so a buffer hiccup can’t make you miss the slot. But the scheduled start time should be exactly the loop point, not a few milliseconds before it. Starting the audio early shortens that pass, and if you compute each start from the previous one instead of from absolute values, the error accumulates over a long session. Schedule against absolute dspTime values and the seam stays exact indefinitely.

Summary

Engine Reads embedded loop points Tail across the seam
Godot Yes, WAV smpl Code, or a folded tail
Unity Yes, undocumented and fragile Code (two AudioSources)
Unreal Cue markers only, not smpl Two Wave Players in a MetaSound
RPG Maker MV/MZ Yes, OGG LOOPSTART Folded tail only
FMOD Studio In the project Transition timeline
Wwise Sound SFX yes; music uses cues Native post-exit playback
GameMaker No Folded tail, or a crossfade
AGS No Folded tail, or a crossfade

A note on how I handle this

I got tired of doing this by hand for every track and every target, so I built a Windows app called Loopsmith that does it: it finds the loop point, renders the loop so the tail survives the seam, writes the right metadata for each format, and builds the setup inside FMOD, Wwise or Unreal. There’s a free demo if it’s useful to you.

But the techniques above aren’t mine and they aren’t new. They’re what the engines and middleware already support, written down in one place because I couldn’t find that when I needed it. If this saved you an afternoon, that was the point.

Austin Haynes is a composer for games, including Cognition: An Erica Reed Thriller (AdventureGamers Best Music of 2013) and The Silver Lining. If your project needs music, you can hear his work at austinhaynesmusic.com.