communication


Browser to unity3d communication and back again

I have been doing a fair bit of unity3d recently again. In particular I have been looking at the ways it can take data and parameters. It’s all in the unity documentation but there were a few subtle things I missed first time around that I thought it worth sharing, as much for my memory as anything.
The first useful thing is the unity plugin is able to simply talk back to the browser and call javascript functions in the page. So in C# for example I am able to do this.

void Awake ()
{
Application.ExternalCall( "callbackunity", "The game says hello!" );
}

Where the page that the unity3d is served from has

<script type=”text/javascript”>
<!–
function callbackunity(arg)
{
alert(arg);
}
–>


Obviously you can do more than just an alert so I looked at what I can send back into unity3d from the page and started to do this in the calling page.

<script type=”text/javascript”>
<!–
function callbackunity(arg)
{
alert(arg);
var unity = unityObject.getObjectById(“unityPlayer”);
unity.SendMessage(“Rezzer”, “inboundfunction”, “item1~item2~item3”);
}
–>
</script>

This gets the unity plugin module and calls a function called inboundfunction that is attached to a unity game object called Rezzer. It is only able to pass a single value so I send a string with a known seperator ~ to be able to send more than one piece of data.
So the flow is that unity loads, awakes and then makes a callback to the page which then injects the data into unity.
On the unity side I have this sort of function

void inboundfunction(string indata)
{

string[] words = indata.Split('~');

data1 = words[0];
moredata2 = words[1];
anotherpiece3 = words[2];

}

At first this all did not work (of course). I thought I had not put the right script on the right object as I was getting a callback to the page but not injecting the data into the unity object.
This turned out to be something quite simple in the end. The unity docs example shows var unity = unityObject.getObjectById(“UnityContent”); However the page I got generated out of unity3d that I used to then add my code to used a different label for the Unity plugin in the setup. It called it “unityPlayer”. So my failing code was because the js in the webpage was not picking up the right object. As we know computers need to have everything exact.
This was almost code blindness. I was thinking it was getting the unity object, of course it was how could it do anything other, but its an obvious school boy error “UnityContent” <> “unityPlayer” 🙂
Once that little bug was sorted out it was all plain sailing. The parameters I pass as item 1,2 3 etc are generated by PHP from Drupal that embeds the unity3d. So I can send anything to the unity based on which page is being served and by whom.
One of the other things I do though is use direct WWW communication to a server from inside the unity3d. This initial set up code is to establish some start parameters, once running communication is not via the browser, but a hotline to server instead.
That all just works as documented, though you have to make sure you are serving from and talking to the same server or dealing with the cross domain policy documents that help protect web apps from rogue applications in browsers.
This is all very basic code really, but if you are not from a web world it can seem a little unusual.
e.g. in .cs in unity3d

IEnumerator sendIt ()
{
// Create a form object
WWWForm form = new WWWForm ();
// set up fields
form.AddField ("data1", "some data");
form.AddField ("userscore", score );

// Create a download object
WWW download = new WWW ("http://someurltohandlethings", form);

// Wait until the download is done
yield return download;

if (download.error != null) {
Debug.Log (download.error);
print ("Error downloading: " + download.error);

} else {
print ("Sent");

}

}

Due to .cs needing to multi thread this is an enumerated function which means you have to call it like this when you want to send anything

StartCoroutine (sendIt ());

As most of my quick unity3d pieces had been in .js this StartCoroutine was not as obvious, though it is in the Unity docs.
The URL I call has some PHP that gets at the form elements, but we are in normal web territory then.

$somedata = $_POST["data1"];
$somescore = $_POST["userscore"];

Of course all the error handling and data handling can (and is) much more elegant but this all seems to work very nicely and the core of the communication I am able to drop into anywhere.