One HTML Template to Rule Them All?

I’m just about to dig into web integration more, and I’m finding four different official sources for how to embed a Unity web player into a page’s HTML:

  1. The auto-generated HTML. Which Dreamweaver (I know, I know, but it has certain uses!) reports as being incompatible with the latest Internet Explorer in some way.

  2. This manual page re making Unity content work in IE/ActiveX vs. others:
    http://unity3d.com/Documentation/Manual/HTML%20code%20to%20load%20Unity%20Web%20Player%20content.html

  3. This manual page which says the auto-generated template doesn’t generate a consistent user experience, and offers alternative plugin-detection code:
    http://unity3d.com/Documentation/Manual/Detecting%20the%20Unity%20Web%20Player%20using%20browser%20scripting.html

  4. This manual page which explains how to work better with ActiveX:
    http://unity3d.com/Documentation/Manual/Publishing%20active%20content.html

Before I try to figure out how those four sources interact, and which ones supersede the others, is there an HTML template already existing for Unity that takes all four of those topics into account? All four seem necessary to insure the best experience and compatibility.

If not, I’ll work on making a template myself that takes all those into account, and will share it with the community.

Once I have that, I intend to add three optional extras to make a more capable version…

  1. Loading screen customization:
    http://unity3d.com/Documentation/Manual/Customizing%20the%20Unity%20Web%20Player%20loading%20screen.html

  2. Bi-directional browser communication:
    http://unity3d.com/Documentation/Manual/Unity%20Web%20Player%20and%20browser%20communication.html

  3. Display of alternate content (be it text, Flash, or ideally a Unity screenshot) for people who don’t have (or choose not to install) the plugin–along with a link to get the plugin of course.

Those seven things, hopefully, will combine to make One HTML Template to Rule Them All :slight_smile: In the process my goal is to make it validate for XHTML and CSS, and use CSS-P with no center tags, tables, or deprecated markup.

And I’ll want it to work (on SOME level) for all browsers, with OR without JavaScript enabled. So that at the very worst, everyone sees the alternate content.

Any advice on integrating those 4… er, 7… topics? Has it been done already?

(I know this may need to be revisited for Unity 2, but meanwhile I want to get the best template working for Unity 1.)

This, #4, looks like is supersedes the other three sources of code.

But I don’t see where the filename, height, and width get specified.

 writeUnityTags();

Is something missing? Should that read:

 writeUnityTags("filename.unityweb","400","300");

?

It looks to me like the auto-generated HTML takes care of #2. I’m thinking of making one single external .js file covering #3, #4, #5 (by adding additional tags to writeUnityTags), and #6. Then a very simple HTML example should be able to call upon it, and games that don’t need #6 simply wouldn’t call those functions (they’re small anyway).

That leaves the issue of browsers which have JavaScript disabled or broken. (Those people could never have browser communication, but they might still be able to use plugins/ActiveX controls.) For that case, I’d add a noscript section to the HTML, containing essentially the same as the auto-generated HTML, with the addition of (optional) Pro loading customizations.

I’m thinking there would be no avoiding the need to specify filename/dimensions/loading customizations three times–once for writeUnityTags and twice (object and embed) in noscript.

The alternate content would also be coded twice: once in noembed, which I would use ONLY within noscript, and once as the “else” response for detectUnityWebPlayer.

Sound reasonable?

Is there any time you would want noembed used within Javascript plugin detection? (I assume that would be redundant and useless, since detectUnityWebPlayer has its own way to deliver alternate content without relying on noembed.)

I’m thinking of writing an app that would let people fill out some info and would then generate the HTML for the above. I might include fancier alternate content, with a screenshot or other image that would server as a graphical “click to get plugin” button, as well as a placeholder to make the page look nice and complete with or without Unity.

This may all have been done to death before now :slight_smile: but my searches came up empty.

I also found this, but am not sure what it offers vs. the other methods:

That’s because it’s not properly “Active Content” friendly. For IE to activate content without first requiring the user to click on the content in question you must use an external JS file that dynamically writes the object/embed tags in the page. The default template doesn’t do that…

All three of those relate to having an external JS file write the proper object/embed tags for all users as well as having proper plugin detection schemes in place, all are very good things to consider when publishing web player content.

Yes. :slight_smile:

I’ve prepared a template file along these lines but it also requires another component, a PERL script that Unity executes after the publish process finishes. I say that because not only will Unity need to generate the *.unityweb data file and HTML file, but it also needs to copy any external files (like your JS script file!) into place next to them (you could manually copy it but who wants to do that?). Therefore I’ve written such a PERL script and to demo its behavior I created a template that uses external JS and all that jazz just as you’re asking about. Additionally, the PERL script is quite flexible in that you can define any number of needed external files (like custom loader graphics, any in-page images, etc.) that will also be copied into place when you build web player content.

What’s more is that you’ll use this PERL script and template (start with mine then drop in your own) on a per-project basis, therefore you can easily customize the template for each project without having to swap in/out template files buried inside the application bundle itself.

Oh, one last bit, my script allows you to use a template in any text based format (HTM, HTML, PHP, CFM, ASP, whatever!) so you can build a much wider variety of web pages to host your content when you press that Build button.

Slick, easy and flexible…

Enough of the sales pitch:
PostprocessBuildPlayer Script

Give that page a read and download the examples archive (all of 100Kb). This should soon make it on to our site as an example project (which is why I’ve held off on posting this to the wiki site).

Have fun and let me know if you have any questions.

Thanks for the info!

Good to know–requiring a click isn’t ideal but it’s hardly a deal-breaker for the default HTML.

Wow–sweet! I wasn’t even thinking of automating the process that far, just making a template for manual installation. (I’ll still work on a template to make certain things as easy as possible.)

Downloading now–many thanks!

I’ll post back with whatever I come up with.

Yeah, I wanted to learn the post-process PERL script feature and I just kind of ran with it for web player publishing… :stuck_out_tongue: Pick it apart and post up any suggested updates/changes/questions!

Are there any examples online of anyone using all the proper techniques to deliver Unity content to the Web?

I’d like to look at them and see how they differ from what I’ve put together based on the manual, which doesn’t work. (I haven’t moved on to your creation yet, but I’m still trying to get the stuff in the manual to work.)

It seems like ALL those documented techniques should be implemented in order to get the best result for everyone. But there seem to be some errors in the scripts in the manual. I’ve fixed a couple that I notice (one that I questioned above, plus a failure of detectUnityWebPlayer to write the tags around its ActiveX detection routine). But the result, while perfect in Safari and Fiefox, still doesn’t work in IE7 (XP SP2–I haven’t tested IE6), with or without those fixes.

After jumping through IE7 hoops warning me against viewing active content, I get a blank screen instead of Unity content, and I don’t even see my alternate content that should appear when Unity is not installed. (But it is, since standard auto-generated Unity pages display Unity content just fine–and without the hoops and warnings.)

My HTML template:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Unity</title>
<script type="text/javascript" language="javascript" src="unityweb.js"></script>
</head>

<body>

<center>

<script language="javascript">
displayUnity("filename.unityweb","alternatefile.jpg","400","300");
</script>
<noscript>
<h2>To view this content, please [url="http://www.google.com/search?q=enable+javascript"]enable "JavaScript" or "Active scripting"[/url] in your browser.</h2>
</noscript>

</center>

</body>
</html>

And my unityweb.js:

function displayUnity (aSrc, aAlt, aWidth, aHeight) {

    // check for the Unity Web Player and respond appropriately
    var tIsInstalled = detectUnityWebPlayer();
    if (tIsInstalled) {

        // call the writeUnityTags function
         writeUnityTags(aSrc, aWidth, aHeight);

    } else {

        // display alternate content
        document.write("[url='http://unity3d.com/unitywebplayer.html'][img]" + aAlt + "[/img][/url]");

    }

}


function detectUnityWebPlayer () {

    // initiailize the installed flag
    var tInstalled = false;

    // check if the page being viewed in Internet Explorer on Windows or not
    if (navigator.appVersion.indexOf("MSIE") != -1  navigator.appVersion.toLowerCase().indexOf("win") != -1) {

        // perform ActiveX detection routine
        document.write("<script language='javascript'> \n");
        document.write("on error resume next \n");
        document.write("set tControl = CreateObject('UnityWebPlayer.UnityWebPlayerAXCtrl.1') \n");
        document.write("if IsObject(tControl) then \n");
        document.write("tFound = 1 \n");
        document.write("else \n");
        document.write("tFound = 0 \n");
        document.write("end if \n");
        document.write("</script> \n");
        tInstalled = (tFound == 1);

    } else {
	  
        // perform plugin detection routine
        if (navigator.mimeTypes  navigator.mimeTypes["application/x-unity"]  navigator.mimeTypes["application/x-unity"].enabledPlugin) {
            if (navigator.plugins  navigator.plugins["Unity Web Player"]) {
			
                // update the installed flag
                tInstalled = true;
	
            }
        }
		
    }
	
    // return the installed flag
    return tInstalled;
	
}


function writeUnityTags (aSrc, aWidth, aHeight) {

    // write the content object and embed tags
    document.write("<object ");
    document.write("    classid='clsid:36D04559-44B7-45E0-BA81-E1508FAB359F' codebase='http://otee.dk/download_webplayer/UnityWebPlayer.cab'  \n");
    document.write("    id='UnityObject' width='" + aWidth + "' height='" + aHeight + "'  > \n");
    document.write("    <param name='src' value='" + aSrc + "' /> \n");
    document.write("    <embed type='application/x-unity' pluginspage='http://otee.dk/getunityplayer.html' \n");
    document.write("        id='UnityEmbed' width='" + aWidth + "' height='" + aHeight + "' src='" + aSrc + "' \n");
    document.write("    /> \n");
    document.write("");

}

Those are straight out of the manual except for the corrections I noted, an additional noscript response, and better no-Unity response (an alternate image instead of just text). All is well except with Windows/IE, it seems.

49703–1826–$failedunitytemplate_763.zip (26.9 KB)

The Unity 2.0 template is completely different, you probably should check that one out. :slight_smile:

Cool–will check it out. Looks similar but I see the missing tags for ActiveX have been added.

The missing arguments for writeUnityTags() still seems to be a problem with the provided code, but one that’s easily fixed.

I’ll report back on whether IE likes the new code.

Actually, the code in the manual doesn’t seem to work in ANY browser. The ActiveX detection now seems to break compatibility with Firefox and Safari.

Has anyone used the manual’s recommended best method instead of the auto-generated one? Any examples out there?

I’m nervous about deploying something that won’t give the best possible experience to the widest audience, and those manual topics are persuasive in making me want to employ the methods they describe.

(BTW, the links in my first post are still good for the new manual.)

OK, in addition to the writeUnityTags(); bug in the manual (two instances here; change to writeUnityTags(aSrc, aWidth, aHeight); ), I found one more error:

In the first code snippet here, change this:

document.write("<script language="VBScript">\n");

to this:

 document.write("<script language='VBScript'>\n");

with single-quotes.

Also, for Unity 1.6 content rather than 2.0, change all instances of vnd.unity to x-unity. (This prevents an “invalid data file” error, according to my trial and error.)

Those changes make the new HTML template info in the manual work in Safari and Firefox. They even deliver the no-plugin alternate content if you don’t have Unity (at least in Safari: I don’t know how to disable the plugin for testing in Firefox).

But I still can’t get anything from Internet Explorer:

  • The auto-generated HTML delivers Unity content OK in EI, except you need to hit spacebar or enter before it will work.

  • But the HTML from the manual (combining all techniques, as described here) gives you a series of vaguely alarming security warnings about “active content” (first a top-bar, then a dialog window) which can only be bypassed by contextual menu, and which return again the next time you view the same page. If you accept the “risks” and go ahead… you get nothing. No Unity content AND no alternate content (message to get the plugin).

What’s next? I’m stumped.

Here’s my HTML and JavaScript (pasted from the manual–but using x-unity since I don’t have Unity 2.0 yet):

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Unity</title>
<script type="text/javascript" language="javascript" src="unityweb.js"></script>
</head>

<body>

<center>

<script language="javascript">
displayUnity("3dchair.unityweb","3dchairalt.jpg","600","600");
</script>
<noscript>
<h2>To view this content, please [url="http://www.google.com/search?q=enable+javascript"]enable "JavaScript" or "Active scripting"[/url] in your browser.</h2>
</noscript>

</center>

</body>
</html>
function displayUnity (aSrc, aAlt, aWidth, aHeight)
{
    // check for the Unity Web Player and respond appropriately
    var tIsInstalled = detectUnityWebPlayer();
    if (tIsInstalled) {
        // call the writeUnityTags function
        writeUnityTags(aSrc, aWidth, aHeight);
    } else {
        // display alternate content
       document.write("[url='http://unity3d.com/getunityplayer.html'][img]" + aAlt + "[/img][/url]");
    }
}


function detectUnityWebPlayer ()
{
    // initiailize the installed flag
    var tInstalled = false;
    // check if the page being viewed in Internet Explorer on Windows or not
    if (navigator.appVersion.indexOf("MSIE") != -1  navigator.appVersion.toLowerCase().indexOf("win") != -1)
    {
        // perform ActiveX detection routine
        document.write("<script language='VBScript'>\n");
        document.write("on error resume next \n");
        document.write("set tControl = CreateObject('UnityWebPlayer.UnityWebPlayer.1') \n");
        document.write("if IsObject(tControl) then \n");
        document.write("tFound = 1 \n");
        document.write("else \n");
        document.write("tFound = 0 \n");
        document.write("end if \n");
        document.write("</script>\n");
        tInstalled = (tFound == 1);
    }
    else
    {
        // perform plugin detection routine
        if (navigator.mimeTypes  navigator.mimeTypes["application/x-unity"]  navigator.mimeTypes["application/x-unity"].enabledPlugin)
        {
            if (navigator.plugins  navigator.plugins["Unity Web Player"])
            {			
                // update the installed flag
                tInstalled = true;
            }
        }
    }
    // return the installed flag
    return tInstalled;	
}


function writeUnityTags (aSrc, aWidth, aHeight)
{
    // write the content object and embed tags
    document.write("<object ");
    document.write("    classid='clsid:36D04559-44B7-45E0-BA81-E1508FAB359F' \n");
    document.write("    codebase='http://unity3d.com/download_webplayer/UnityWebPlayer.cab#version=2,0,0,0' \n");
    document.write("    id='UnityObject' width='" + aWidth + "' height='" + aHeight + "'  > \n");
    document.write("    <param name='src' value='" + aSrc + "' /> \n");
    document.write("    <embed type='application/x-unity' pluginspage='http://unity3d.com/getunityplayer.html' \n");
    document.write("        id='UnityEmbed' width='" + aWidth + "' height='" + aHeight + "' src='" + aSrc + "' \n");
    document.write("    /> \n");
    document.write("</object\>");
}

Thanks for any advice. I plan to post on the wiki a “basic” template and an “advanced template” (which will add loading customization and browser communication). Once they work :slight_smile:

Now that 2.0 and Unity are settling down (maybe?), I thought I’d check again. Has anyone successfully implemented the code in the manual that creates the best experience for webplayers?

I intend to contact a bunch of people this week to see if I can get them to use Unity for Web stuff (with my company’s support, naturally!) and I want my Web demos to be the most polished they can be–in all the ways the manual suggests–so that they are convinced their users will have no problem with Unity content.

(I intend to update my webplayers to 2.0 so they don’t have to download two players. Hopefully that will remove one level of complexity.)

Hey Morgan, now that I have handed in my resignation at work I’ll have most of November to take a look at what you’ve done. And since my “real” job is this stuff, I hope to help you out.

Cool–more heads are better than one :slight_smile:

I’ve already gone ahead and made a “deluxe” template too, with loading graphics and browser communication (all sticking close to the manual). But since even the basic template does not work for me (a 1.x vs. 2.x issue possibly?) I’m troubleshooting the simple one first.

@Morgan: sorry for dropping off this thread, I’m going to read over everything here once again and offer some thoughts when I’m done.

I’m still trying to get all my web players converted and reorganized to work with Unity 2.0, but you can see the work in progress at

http://www.fugugames.com/unity.html

I started with the default HTML generated by Unity 2.0 and then moved the content-generating javascript into a WriteUnity function as recommended by the Publishing Active Content section of the manual. Eventually I expect to move that function into an external javascript file per the manual, not just for the reason mentioned in the manual but also so it can be reused easily in multiple web pages. However, it’s not clear to me from the manual where the VBScript for detecting Unity should go - can that be placed inside a .js file? And I recall there was some problem with Unity 1.x using an external javascript file with IE, so I don’t know if that’s solved and how with this new HTML.

I didn’t add width/height parameters to the WriteUnity script because so far I never vary them. I do pass in the src, logoprogressimage and disableContextMenu params so I don’t have to type each of them five times every time I change them. By the way, logoprogressimage doesn’t seem to work on Windows at all, in IE, Firefox or Opera (I didn’t realize Opera worked with Unity - pleasant surprise!)

The other reason I parameterized WriteUnity is because I want to switch among web players in one web page instead of generating a new web page for each - if I have a dozen web players, I don’t want to have to edit every web page every time I tweak my web site. I considered using the post-build perl script feature to generate a custom page for each player, but I have a separate project for each player and I’d have to add/maintain the script for each, and then I’d still have to rerun the build for each player for a web site change.

With Unity 1.x, I was using LoadUnityWeb inside an initial menu player to load all the other players, but that seems to broken in 2.0, so I’m experimenting with an HTML drop-down list of web player names that writes the new player name to a cookie and then reloads the page, and the javascript reads the cookie and calls WriteUnity with the last-saved game name. This seems to work fine on Mac and Windows for Firefox, Safari and Opera, and not yet for IE, but I’m still holding out hope.

I had another idea that I thought might be cleaner - the javascript for the player name selector would go through the DOM and replace the src attributes with the new player name. This worked for Firefox, Opera and IE, but not Safari!

Tom: Thanks for any help :slight_smile: I really think it’s important to the Unity platform that Unity content work as best it can for everyone. (As the manual already stresses.) Flash has generally been very good about that–the author can trust the auto-generated template to work reliably.

Even if the Unity template can’t be automatically that good, I’d like to make it as easy as possible for people to achieve that.

technicat : That’s a thought–maybe the VB stuff can’t be in a JS file. But I’m thinking that’s OK: the JS file simply writes to the doc, creating the VB stuff on the fly.

I’ve got a template that uses ONE line of code to display Unity content in the best way for all browsers, with all the bells and whistles, complete with an alternate JPEG, custom load screen, and browser communication support:

displayUnity("filename.unityweb","alternatefile.jpg","400","300","FFFFFF","000000","loadinglogo.png","emptyloadbar.png","fullloadbar.png");

However, before that’s of use, I need to get the JavaScript from the manual working in all the recommended ways.

If it’s raw VBScript then you must either (a) include it in the page itself in VBScript form (see the Unity 2.0 default HTML template), (b) in an external *.vb file (I don’t have experience with that), or (c) written into the page via some JavaScript (whether that JavaScript is in the page or external to the document).

There’s nothing unique to the 1.x player in this regard that doesn’t also appear in the 2.0 player (the “problem” in Win IE is the need to use an external JS file so the user doesn’t have to activate the content before interacting with it).

I’d still recommend looking into the PERL script technique, the script is easy enough to modify for a simple republish or you can of course just hand-edit the files anyway. I just don’t want you over-looking a potential time saver during the dev cycle. :slight_smile:

Argh the EOLAS patch – this is what happens when you get code written by lawyers.

Unfortunately, the code that currently embeds Unity stuff inside a web page is pretty ugly. A simple refactoring would reduce it to a single line invocation and eliminate the EOLAS patch issue. It would also let you edit the dimensions of your plugin in one place versus two (or four… see below).

(Incidentally, I see no reason to include noscript support – what are the odds of someone having a browser that supports Unity and has JavaScript disabled…? Anyone running such a browser deserves what they get.)

Oh – and be careful with writing code out from JavaScript code, or writing JavaScript code that interoperates with dynamically written JS code. Order of execution in such cases is highly browser-specific (and not obvious).

FYI, I’ve fixed that particular bug in our help system so with the next product update you’ll see that doc update as well.

Umm sorry to crash this party but let me get something clear.

If I build a webplayer using the 1.6.2 default page, and someone on windows without the plugin opens it:

  1. It might not work.
  2. It might not redirect them to the plugin webpage.
  3. It probably will have the activex warning at the top of the window…

And if there was a third file, a javascript next to the html and unityweb files, that could disable the activex warning?

I see some references to the plugin page in the default html;
http://www.otee.dk/getunityplayer.html” />"

and

On The Edge - Det bedste fra tech verdenen”>

But otee is obsolete and Im assuming the webpage will autoredirect? I’m asking because its easier than fixing my windows box and un/reinstalling the webplayer, and to let my xp machine go online is a recipe for virus disaster.

Theres been a lot of talk about the html page and as Morgan pointed out, theres a lot of different versions around. Whats the go with just having one version that works, on windows as well, and restoring complete functionality so people with windows machines and no plugin can figure it out? Its all rather confusing.

One template to rule them all. Please, no more confusion…

I just want to sell failsafe webplayers I know will work, and I dont understand what the html page says.
/rant
Thanks
AC