A custom preloader in Unity part 3/3

The third and final alternative. Lemme warn you, its complicated, but its worth it. Because you will be able to make a flash preloader for a unity scene, which basicly gives you the ultimate freedom (well unless you wanna have a 3D preloader, then refer to part 2 of this tutorial).

There’s 4 components to this solution.

  • main unity file – the actual, 100 MB unity file which contains your awesome game
  • unity preloader file – this is a very, very minimal preloader written in unity, which receives a query parameter containing the movie to load and will use Application.ExternalCall to inform it’s html page of the loading progress. It’s reusable and you can download it here.
  • swf preloader file – this is a relatively small flash movie, which will show the graphics of your preloader. It will use ExternalInterface.addCallback to listen to the events the unity-preloader fires.
  • javascript/html framework – you’ll need some javascript to receive calls from unity and relay those to flash. You’ll also need to hide and show the swf and unity files when it’s appropriate

Once you downloaded the preloader and you have a little flash preloader animation which listens to ExternalInterface, your biggest problem will be to make the hosting html page a bit organized.

u3d logo

swf logo

Component lifetime

What I did, was use swfobject to load the flash movie and u3dobject to load the unity movie.

u3dobject offers loads of premade functionality to communicate between flash and unity, which I am not using because this wrapper is more complex then the original code (for this purpose) and it’s extra bytes which we don’t want in a preloader. I imagine for larger applications it’s invaluable because it allows flash movies to listen to unity events and visa versa in a very elegant way.

To the left here, you can see a little diagram of the lifetime of these 4 components. Made with the most time-saving UML tool out there: mspaint.

You can see an example of this method here:

http://kominski.net/demo/unityswfpreloader/

It’s actually a bit of a bad example, since in this version you have to click the image to see the preloader (or if its loaded the unity scene directly).

So, to make the flash preloader, add the following code to your document class constructor:

ExternalInterface.addCallback("onPreloadStart", onPreloadStart);
ExternalInterface.addCallback("onPreloadProgress", onPreloadProgress);
ExternalInterface.addCallback("onPreloadCompleted", onPreloadCompleted);

and then the definitions for those functions:

private function onPreloadStart():void {
	// called when the preloader.unity3d starts actually loading the main unity file
}
 
private function onPreloadProgress(progress:String):void {
	// progress contains a number from 0.0 to 1.0 indicating progress
}
 
private function onPreloadCompleted():void {
	// called when the preloader.unity3d finished loading and is about to call stream.LoadUnityWeb()
}

Your html page will not look much like the generated unity template, but it’s based on the u3dobj template. Here’s the short version of what it will look like:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
    <script src="js/jquery.js" type="text/javascript"></script>
    <script src="js/u3dobject.js" type="text/javascript"></script>	
	<script src="js/unitydetect.vbs" language='VBScript'></script>
	<script src="js/swfobject.js" type="text/javascript"></script>
    <script type="text/javascript">
 
	function initialize()
	{
		load_flash();
		load_unity();
	}
 
	function load_flash()
	{
		var flashvars = { root_url: " "};
		var params = { 'allowScriptAccess': 'always'};
		var attributes = {};
		attributes.id = "flash_content";
		swfobject.embedSWF("swf/preloader.swf", "flash_content", "600", "450px", "9.0.0", "swf/expressInstall.swf", flashvars, params, attributes);	
	}
 
	function load_unity()
	{
		var options = {
			width:600,
			height:450,
		};
		$("#div_unity").embedUnity('unity/preloader.unity3d?file=unity/main.unity3d', options);
		hide_unity();
	}
 
	function hide_unity()
	{		
		$.u3dobject.hide("div_unity"); // doesnt work in jquery syntax
	}	
 
	function show_unity()
	{	
		$("#flash_content").hide();
		$.u3dobject.show("div_unity"); // doesnt work in jquery syntax
	}
 
	function onPreloadStart()
	{	
		var el = document.getElementById("flash_content");		
		if( el ) el.onPreloadStart();
	}
 
	function onPreloadProgress(progress)
	{
		var el = document.getElementById("flash_content");
		if( el ) el.onPreloadProgress(progress);
	}
 
	function onPreloadCompleted()
	{
		// todo: wait just 2 sec before running the next line to give unity time to unpack
		show_unity();
	}
    </script>
    <link href="css/default.css" rel="stylesheet" type="text/css" />
</head>
 
<body onload="initialize();">
<div id="flash_content"></div>
<div id="div_unity"></div>
</body>
</html>

And that should do it. I have not elaborated too much on stuff because it’s an advanced topic so you don’t want too much clutter. If you have questions, just post a comment, I’ll be happy to answer.

Tags: , , , , ,

2 Responses to “A custom preloader in Unity part 3/3”

  1. Alex says:

    Hi, would you be willing to provide your source for the little preloader file? I have everything working, but when I load a file compiled with Unity Pro, all of the pro features like shadows are turned off. I can recompile and send back to you if that would help.

  2. admin says:

    Hey alex, sorry ’s been a while since I checked this, I must have the source somewhere back home. It was indeed compiled with the Indie version of unity.

Leave a Reply

Security Code: