/// <summary>
        /// Unloads the current level and loads the new level
        /// </summary>
        private void LoadLevelNow(LevelChangedEventArgs args)
        {
            Level newLevel = args.NewLevel;

            // Unload current level
            UnloadLevel(args);

            CurrentLevel = newLevel;

            // Load new Level
            if (newLevel != null) {
                Launch.Log("==========================================================");
                Launch.Log("======= Level loading: " + newLevel.Name + " =======");
                Launch.Log("==========================================================");

                // load our resource group, if we have one
                InvokeLevelProgress(args, "Initialising new resource group...");
                if (ResourceGroupManager.Singleton.ResourceGroupExists(newLevel.Name) && !ResourceGroupManager.Singleton.IsResourceGroupInitialised(newLevel.Name)) {
                    Launch.Log("[Loading] Initialising resource group: " + newLevel.Name);
                    ResourceGroupManager.Singleton.InitialiseResourceGroup(newLevel.Name);
                }

                // load up the world definition from the .muffin file
                InvokeLevelProgress(args, "Reading .muffin files...");
                newLevel.ReadMuffin();

                // set up shadows, create stuff in the .scene file, and set up physics
                InvokeLevelProgress(args, "Reading .scene file and setting up shadows and physics...");
                LKernel.GetG<SceneManager>().SetupShadows(newLevel);
                newLevel.ReadDotSceneAndSetupPhysics();

                // run our level loading events
                Launch.Log("[Loading] Loading everything else...");
                InvokeLevelProgress(args, "Invoking level load event...");
                Invoke(OnLevelLoad, args);

                // then put Things into our world
                InvokeLevelProgress(args, "Creating entities...");
                newLevel.CreateEntities();
                // then load the rest of the handlers
                InvokeLevelProgress(args, "Loading level handlers...");
                LKernel.LoadLevelHandlers(newLevel);

                IsValidLevel = true;

                if (IsPlayableLevel)
                    LKernel.GetG<PhysicsMain>().StartSimulation();

                // run our scripts
                InvokeLevelProgress(args, "Running scripts...");
                LKernel.GetG<LuaMain>().LoadScriptFiles(newLevel.Name);
                newLevel.RunLevelScript();
                newLevel.RunThingScripts();

                InvokeLevelProgress(args, "Building static and instanced geometry...");
                LKernel.GetG<StaticGeometryManager>().Build();
                LKernel.GetG<InstancedGeometryManager>().Build();
            }

            // if we're on the main menu, pause it
            if (newLevel.Name == Settings.Default.MainMenuName)
                Pauser.IsPaused = true;

            // last bit of cleanup
            InvokeLevelProgress(args, "Garbage collecting...");
            GC.Collect();

            // post load event needs to be delayed
            if (newLevel != null) {
                // reset these
                elapsed = 0;
                frameOneRendered = frameTwoRendered = false;

                // set up our handler
                postLoadFrameStartedHandler = new FrameListener.FrameStartedHandler(
                    (fe) => {
                        return DelayedRun_FrameStarted(fe, INITIAL_DELAY, (a) => { Invoke(OnLevelPostLoad, a); }, args);
                    });
                LKernel.Get<Root>().FrameStarted += postLoadFrameStartedHandler;
            }
        }
        /// <summary>
        /// Loads a level!
        /// </summary>
        /// <param name="delay">
        /// Minimum time to wait (in seconds) before we load the level, to let stuff like loading screens have a chance to render.
        /// Pass 0 to load the new level instantly.
        /// </param>
        public void LoadLevel(LevelChangeRequest request, float delay = INITIAL_DELAY)
        {
            Pauser.IsPaused = false;
            var eventArgs = new LevelChangedEventArgs(new Level(request.NewLevelName), CurrentLevel, request);

            // fire our preUnload events
            Invoke(OnLevelPreUnload, eventArgs);

            if (delay > 0) {
                // we need to have this because otherwise we start loading before we manage to render a frame, and we need to render a frame to
                // show stuff like a loading screen

                // reset these
                elapsed = 0;
                frameOneRendered = frameTwoRendered = false;

                // set up a little frame started handler with our events
                preUnloadFrameStartedHandler = new FrameListener.FrameStartedHandler(
                    (fe) => {
                        return DelayedRun_FrameStarted(fe, delay, LoadLevelNow, eventArgs);
                    });
                LKernel.Get<Root>().FrameStarted += preUnloadFrameStartedHandler;
            }
            else {
                // if our delay is 0, just load the level and don't do any of the delayed stuff
                LoadLevelNow(eventArgs);
            }
        }