Many people are having problems building and embedding their Unity game in a Flash Builder project. This is largely due to insufficient documentation, bugs in the unity flash compiler, and a general lack of knowledge. This document aims to fill this gap by describing in detail how to build your Unity game, embed it in a Flash Builder project and explains how to communicate between both projects. The final project can be downloaded here, it features a working sample of sending complex data from and to Unity.
The target is to implement it in an AIR application, but regular Flash-web projects should work as well.
Before starting you'll need the following:
Personally i use Unity Pro and Unity Flash Pro, though i dont think this is required, Unity Basic and Flash Basic will suffice. You can download a trial of Adobe Flash Builder 4.6 here. (Note: The latest version (4.7) doesnt have a way to view your design, so i choose 4.6 instead.) Also this tutorial will use C# as scripting language for Unity, and (obviously)Actionscript for Flash.
Firstly you should read the available documentation thoroughly. It covers many basic aspects of Flash development, and is a good headstart. Sadly not everything is covered as much as you'd like, and a lot of flash-specific information is not explained in a way a non-flash developer would understand. For example, the Flash Setup page explains -swf version should be set to 15, /fp should be 11.2 and wmode should be direct. What isnt explained is what those settings are or how to set them.
You should setup debugging as per the manual. The flash log will contain vital information for when things go bad during runtime. Also all Debug.Log statements can be found in the Flash logs, and when debugging in Flash Builder it will be visible in the console window.
Another good resource are the Flash Development forums, it contains some good samples on embedding as well, although questions there mostly go unanswered.
Flash player 11 introduced Stage3D, which is a library for Flash developers to use hardware accelerated content. It grants Flash developers access to hardware accelerated graphics, shaders and all other capabilities game developers have been using for years to create awesome content.
Sadly the only way to use this content is via Actionscript, this is why when you build your Unity project it converts all your code to Actionscript. You can find the converted code here: Temp\StagingArea\Data\ConvertedDotNetCode\global.
Building the project usually is a fairly easy task, though some changes to the code may be required. The process usually goes like this:
Most problems can be solved by editing your source script, though its also possible to convert the class by hand. This is described in the manual here, abeit not completely.
After fixing all the errors the project should build properly, and run correctly in your browser using the supplied .swf and .html files. Rejoice! This was the 'easy' part of publishing to flash, and you should now be able to submit your game to any online portal you desire.
The next step of this tutorial is embedding it with a Flash Builder project. This is useful if you want to create your UI in Flash Builder, or perhaps embed the project in an existing Flash application. This proved to be most difficult for me, a non flash developer. After actually figuring it out it seems quite trivial, you just have to know some specific settings and flash-tricks. The goal for this tutorial is:
The project we'll use is fairly simple, it has one component on a GameObject with the name "FlashManager". The scripts contents are as follows:
First we'll create our Flash Builder project, open Flash Builder 4.6 and go to File > New > Flex Project. Give the project a name, and optionally change the location. This tutorial explains how to embed your unity build in an Adobe AIR project, so select AIR under Application Type. Leave the SDK version on default (4.6) and click Finish.
The first document opened is (projectname).mxml, this is an XML file where you'll define the layout and visual elements in your application. For Silverlight developers, this is your XAML file. Another file that is generated is (projectname).xml, this contains some very important settings which we'll discuss later on.
Now go back to Unity to build your project, and save it as "build". Examine the resulting files, the ones that are important are: embeddingapi.swc and build.swf. The SWC file is like a DLL, it contains some classes which you'll need in order to embed Unity. Drag that to the libs/ folder in Flash Builder. The second .swf file contains the actual player, this is loaded in the scene and renders your project. Drag this in the default package, next to the existing .mxml file.
Next up is creating an Actionscript class that loads and displays our Unity SWF file. This is partially described in this part of the manual. Begin by creating a new Actionscript class in the default package (Right mouse in Package explorer, New > ActionScript Class). You can safely ignore the warning Flash Builder presents about classes in the default package. Name your new class UnityLoader and click finish.
The contents of UnityLoader.as should be as follows:
Now we have to add it to our view, doing this requires 2 steps: Adding the namespace and declaring the Loader. Open yor .mxml file and make sure you are in Source mode. Add this attribute to the root element (s:WindowedApplication): xmlns:local="*", this includes the namespace so you can access UnityLoader. Then add <local:UnityLoader /> to the view. Great! We've created a loader and added it to the scene, we're almost done. Right?
Debug the build by pressing the following button:
There are 2 settings to adjust in order to make your view visible, namely:
Try debugging the project again, unity should run just fine now! You can even add more GUI elements in the scene, they are all displayed nicely along Unity. Are you still having problems? Scroll all the way down for a few issues and solutions.
Its important to realise your code is translated and executed as Actionscript. Though it is not easily accessible by the Flash Builder project, because its built in the SWC file. (If this is untrue, please let me know!). It still is possible to send complex data structures to Flash, by emitting some Actionscript yourself.
We'll start by trying to send an object from Flash, to Unity. Lets add a button to the scene, and send our ExampleObject when you click on it. Add the following code to your .mxml file:
UnityLoader.SendMessage is defined as follows:
Great, now we can use our old familiar friend SendMessage. Lets go back to Unity and actually receive the object! The problem is, we cant just accept ExampleObject as parameter in our ReceiveExampleObject method, nor cast an Object to ExampleObject, the type we send and receive are not compatible. When you try that anyway you get the following error: Instead we'll do the following: Emit some ActionScript code ourself that sets all properties on our type. That sounds like a lovely little hack doesnt it! Complete the ReceiveExampleObject function in TestScript.cs with the following code: Again its actually fairly straightforward. When we are using Flash the object is first cleared, then each property is extracted. If you have a hard time understanding this you should look at the generated actionscript, it should make more sense.
Build the player and update the build.swf file, then run the project. Everything should work just fine now, whenever you press your button a new random int is displayed, and the other fields are updated as well.
Great, now we have Flash chatting to Unity, now lets try to send a message to Flash. This is a little bit more complicated. In order to communicate we'll need to get a reference to the UnityLoader object we have in Flash. Once we have that we can call any function on this object, with any argument we'd like. Extend UnityLoader.as with the following method: Simple enough, when Unity is done send our current object to the FlashManager. We'll use this reference to call any function on the loader. The second function is the actual method called by Unity. As you can see the argument has the same properties as our ExampleObject.
Lets store the responder in Unity, and call some functions on it! Open up Testscript.cs in Unity and add the following code: The first method is called when Unity is loaded to get the reference to the UnityLoader object. It stores the reference as a private variable, so we can use it later on.
Next we implement SendExampleObject, which is called in the OnGUI. This in turn calls SendFlashMessage, which calls a function on our responder object.
Make sure TestScript is still on FlashManager, build it and move the build.swf in the Flash Builder project, overwriting the old one. Debug (f11) it and behold, when you click on the flash button it sends our ExampleObject to Unity, when you click on the Unity button it sends it back. It will be visible in the console window. Click here to download the complete project if you got stuck somewhere.
By default Unity updates all the time, even when the mouse is not in the current viewport. This causes any mouse-logic to also occur when you use other controls on the canvas. Add this method to FlashManager, will check if the mouse position is within the viewport. Its quite simple, the responder object we've sent before has additional properties about the position and dimensions of the control. We extract those and then do a simple rect check. Before doing anything mouserelated you should check if its actually within the screen.
Still having problems? These are the issues i've faced when trying to embed my project.
Questions or suggestions? Please post them in the forum so everyone can read them, and perhaps the solution can help a fellow coder from the future. You can also email me directly with questions. Keep in mind im not affiliated with Unity in any way, only that i have a strong love-hate relationship with their awesome products.