         .get(@)
         .to({currentFrame:@scrubbingTo}, scrubDuration, createjs.Ease.sineInOut)
         .call(onTweenEnd)
-      t.addEventListener('change', @playScrubbedSounds)
+      t.addEventListener('change', @onFramesScrubbed)
     else
       @currentFrame = @scrubbingTo
-      @playScrubbedSounds()
+      @onFramesScrubbed()  # For performance, don't play these for instant transitions.
       onTweenEnd()
 
     @updateState true
     @onFrameChanged()
 
-  playScrubbedSounds: (e) =>
-    # gotta play all the sounds, even when scrubbing!
-    rising = @currentFrame > @lastFrame
-    actualCurrentFrame = @currentFrame
-    tempFrame = if rising then Math.ceil(@lastFrame) else Math.floor(@lastFrame)
-    while true  # temporary fix to stop cacophony
-      break if rising and tempFrame > actualCurrentFrame
-      break if (not rising) and tempFrame < actualCurrentFrame
-      @currentFrame = tempFrame
-      frame = @world.getFrame(@getCurrentFrame())
-      frame.restoreState()
-      for thangID, sprite of @spriteBoss.sprites
-        sprite.playSounds false, Math.max(0.05, Math.min(1, 1 / @scrubbingPlaybackSpeed))
-      tempFrame += if rising then 1 else -1
-    @currentFrame = actualCurrentFrame
-
-    # TODO: are these needed, or perhaps do they duplicate things?
+  onFramesScrubbed: (e) =>
+    if e
+      # Gotta play all the sounds when scrubbing (but not when doing an immediate transition).
+      rising = @currentFrame > @lastFrame
+      actualCurrentFrame = @currentFrame
+      tempFrame = if rising then Math.ceil(@lastFrame) else Math.floor(@lastFrame)
+      while true  # temporary fix to stop cacophony
+        break if rising and tempFrame > actualCurrentFrame
+        break if (not rising) and tempFrame < actualCurrentFrame
+        @currentFrame = tempFrame
+        frame = @world.getFrame(@getCurrentFrame())
+        frame.restoreState()
+        for thangID, sprite of @spriteBoss.sprites
+          sprite.playSounds false, Math.max(0.05, Math.min(1, 1 / @scrubbingPlaybackSpeed))
+        tempFrame += if rising then 1 else -1
+      @currentFrame = actualCurrentFrame
+
+    @restoreWorldState()
     @spriteBoss.update true
     @onFrameChanged()
 

    @stage.removeAllEventListeners()
    @stage.enableDOMEvents false
    @stage.enableMouseOver 0
    @playScrubbedSounds = null
    @onMouseMove = null
    @onMouseDown = null
    @tick = null

  onNewWorld: (event) ->
    return unless event.world.name is @world.name
    @casting = false

    # This has a tendency to break scripts that are waiting for playback to change when the level is loaded
    # so only run it after the first world is created.
    Backbone.Mediator.publish 'level-set-playing', { playing: @wasPlayingWhenCastingBegan } unless event.firstWorld
