How to do Loading Screens

Started by
24 comments, last by acid2 18 years, 10 months ago
Hi, I was wondering how developers create loading screens. The only sensible way I can think of is if data is loaded in small, discrete chunks. However, the chunks would have to be able to be loaded in 1/60th of a second, so that the program can go through the render loop and present the loading screen at a good framerate. In other words, the first character's data would be loaded, the loading animation would render a frame, then the first character's data will be manipulated to suit the current level, then another frame is rendered, then the second character's data is loaded, etc. But this seems like a real pain, breaking up your data into such small pieces. Is there another way to do it? Thanks. -Gauvir_Mucca
Advertisement
I'ld create another thread which were loading the data. Then when it's done loading it'ld set a bool variable to true and close itself, and when the first(rendering) thread sees that this flag has been set it'll go on to the menu screen(or whatever you need after the loading screen).
Firstly have you ever seen a loading screen with smooth refresh? I haven't. Every load screen I know of (ok not every, but 95% of them anyway) jitter up in huge jumps and don't really give you any acurate feedback. BF1942 had a habbit of getting 95% complete in 5 seconds then sitting there for another 3 mins doing nothing in particular, and I think it was Tribes Vengance did the opposite - it would get to about 50% really slowly then suddenly finished. If you get something like fraps which tells you the framerate you'll see that most of them are only redrawn once or twice a second if that.

All you really need todo is update the loading screen after each mesh/texture rather than cutting them up. And even then you can probably get away with loading batches at a time. The loading screen is really just a nice way to say "Hey this program hasn't crashed - just wait a sec", so the accuracy isn't that important. Personally I just have a big list of models I want to load, then after each load I update the loading screen then move onto the next one. Its not smooth because each model takes a different amount of time to load (health pickup is almost instant where as the level mesh is a few seconds) but nobody has every complained or even noticed :D
The loading system I saw for PS2 (where you can't do threads) basically did what the AP suggested. Each loadable item was split into small chunks. Then an OO-version would be:
class LoadableObject{StartLoad();ContinueLoad();EndLoad();}
So the first method did the initilisation, then ContinueLoad would load a small amount of data and finally EndLoad did any tidying.

I actually use a loading thread. By using Sleep(time) I can set the max fps for the load-screen rendering to optimise time sepnt actually loading the data. It works very well.
Quote:Original post by d000hg
The loading system I saw for PS2 (where you can't do threads) basically did what the AP suggested. Each loadable item was split into small chunks.


The actual data itself wasn't split into seperate files though (which I think was what the AP wasn't happy with). You just load your one mesh file till either its finished or you've reached your time limit then just pause while loading screen updates then continue loading. So your while loop might looke something like:

while ((pos < fsize) && (time < MAX_LOAD_TIME)){   ... loading code ...}// if we've finished loading say soif (pos >= fsize)   return 1;else if (time >= MAX_LOAD_TIME)   return 0; // still need more loadingelse   return -1; // error or something


so you just keep calling this while rendering the loading screen every time it returns. When you get 1 you move onto your next model till your done. Personally I havent' bothered, but if your loading very large files (which I'm not) then its definatly a good option and much simpler than a second thread.
To have it load smoothly, you're going to have to split the process into two different threads. One thread would be responsible for loading the data and outputing the status of what it's loading while the other would be responsible for displaying the status of the background process. If you have access to the .NET framework, you'll be using the System.Threading namespace.
Rob Loach [Website] [Projects] [Contact]
As already said - you don't need threads for this. But it's prabably easier to use them then rewrite how every different file type is loaded. Because the jobs of the two threads don't need to be related at all, you can escape all the nasty side of multithreaded programming.
From a UI feedback point of view, I think I would argue that a jerky progress meter is actually BETTER than a very smooth one, particularly with long loads (e.g. 20+ seconds). No progress meters are ever continuous, and by now users have been conditioned to expect the jumping. Furthermore, they can hear the hard drive clicking away, and when the progress bar is tied to that clicking it provides a level of reinforcement (yes, this is really doing something, please be patient) that a calmly scrolling bar in the face of intermittent HD activitiy does not have.

It is a problem when games decide that they will assign each file a percentage of the progress bar (20 files, so each one is 5% right?), then load 95% of them in 4% of the time and sit there for 30 seconds without changing. I think it's important to identify which files take longer to load (file size alone may be enough) and assign them larger percentages. It's also important to make sure that the progress bar is never still for more than 5-10 seconds, to reassure people that nothing has frozen.

I've seen some programs (compression and installation programs, for example) that actually use two progress bars - one for the "total progress," and one for the processing of the current file after it's been loaded into memory (like when the program is creating a BSP or unencrypting or whatever). I always thought that that was a particularly effictive bit of UI.
--Riley
Quote:Original post by d000hg
Because the jobs of the two threads don't need to be related at all


Actually they do definatly need to be linked. How do you know what percentage to display if they aren't related at all? Thats also a problem in general that sometimes different things will load at different speeds on different machines. The first time you load a level the IO might be slowest, but then next time its already cached so the IO is pretty quick and its the BSP creator thats slower. So if you've said 50% is IO and 50% is bsp creation then on two different runs of your program the meter will move differently (first time 1st half will be slower, 2nd time 2nd half will be slower). You'll never be able to acuratly say how much of the loading is complete - a good guess is all you have which is why I've never bothered to split up loading into chunks or create another thread. Even if I do all that I still have to just 'best guess' at how much time each section takes so I don't thing you gain anything.
I use threads, and while it can be tricky, I think it is worth it, because if you ever decide you want to stream data in without a loading screen, you can. This is useful to have large continuous worlds without breaking it up every few steps to load the next area. Also, nobody says you really need a percent done indicator on your loading screen. A lot of games don't have them, and really, all you need is some animation to show the program hasn't crashed.

tj963
tj963

This topic is closed to new replies.

Advertisement