{"id":1119,"date":"2011-03-09T10:57:15","date_gmt":"2011-03-09T09:57:15","guid":{"rendered":"http:\/\/www.feedingedge.co.uk\/blog\/?p=1119"},"modified":"2011-03-28T13:38:15","modified_gmt":"2011-03-28T12:38:15","slug":"browser-to-unity3d-communication-and-back-again","status":"publish","type":"post","link":"https:\/\/www.feedingedge.co.uk\/blog\/2011\/03\/09\/browser-to-unity3d-communication-and-back-again\/","title":{"rendered":"Browser to unity3d communication and back again"},"content":{"rendered":"\n<div class=\"twitter-share\"><a href=\"https:\/\/twitter.com\/intent\/tweet?via=epredator\" class=\"twitter-share-button\">Tweet<\/a><\/div>\n<p>I have been doing a fair bit of <a href=\"http:\/\/www.unity3d.com\">unity3d<\/a> recently again. In particular I have been looking at the ways it can take data and parameters. It&#8217;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.<br \/>\nThe 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.<br \/>\n<code><br \/>\nvoid Awake ()<br \/>\n\t{<br \/>\n\t\tApplication.ExternalCall( \"callbackunity\", \"The game says hello!\" );<br \/>\n        }<br \/>\n<\/code><br \/>\nWhere the page that the unity3d is served from has <\/p>\n<p> &lt;script type=&#8221;text\/javascript&#8221;&gt;<br \/>\n&lt;!&#8211;<br \/>\nfunction callbackunity(arg)<br \/>\n{<br \/>\n\talert(arg);<br \/>\n}<br \/>\n&#8211;&gt;<\/p>\n<p><\/code><br \/>\nObviously 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.<\/p>\n<p>&lt;script type=&#8221;text\/javascript&#8221;&gt;<br \/>\n&lt;!&#8211;<br \/>\nfunction callbackunity(arg)<br \/>\n{<br \/>\n       alert(arg);<br \/>\n\tvar unity = unityObject.getObjectById(&#8220;unityPlayer&#8221;);<br \/>\n\tunity.SendMessage(&#8220;Rezzer&#8221;, &#8220;inboundfunction&#8221;, &#8220;item1~item2~item3&#8221;);<br \/>\n}<br \/>\n&#8211;&gt;<br \/>\n&lt;\/script&gt;<\/p>\n<p>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.<br \/>\nSo the flow is that unity loads, awakes and then makes a callback to the page which then injects the data into unity.<br \/>\nOn the unity side I have this sort of function<br \/>\n<code><br \/>\nvoid inboundfunction(string indata)<br \/>\n{<\/p>\n<p>string[] words = indata.Split('~');<\/p>\n<p>data1 = words[0];<br \/>\nmoredata2 = words[1];<br \/>\nanotherpiece3 = words[2];\t<\/p>\n<p>}<br \/>\n<\/code><\/p>\n<p>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.<br \/>\nThis turned out to be something quite simple in the end. The <a href=\"http:\/\/unity3d.com\/support\/documentation\/Manual\/Unity%20Web%20Player%20and%20browser%20communication.html\">unity docs<\/a> example shows var unity = unityObject.getObjectById(&#8220;UnityContent&#8221;); 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 &#8220;unityPlayer&#8221;. 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.<br \/>\nThis 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 &#8220;UnityContent&#8221; <> &#8220;unityPlayer&#8221; \ud83d\ude42<br \/>\nOnce 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.<br \/>\nOne 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.<br \/>\nThat 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.<br \/>\nThis is all very basic code really, but if you are not from a web world it can seem a little unusual.<br \/>\ne.g. in .cs in unity3d<br \/>\n<code><br \/>\nIEnumerator sendIt ()<br \/>\n{<br \/>\n\t\t\/\/ Create a form object<br \/>\n\t\tWWWForm form = new WWWForm ();<br \/>\n\t\t\/\/ set up fields<br \/>\n\t\tform.AddField (\"data1\", \"some data\");<br \/>\n\t\tform.AddField (\"userscore\", score );<\/p>\n<p>\t\t\/\/ Create a download object<br \/>\n\t\tWWW download = new WWW (\"http:\/\/someurltohandlethings\", form);<\/p>\n<p>\t\t\/\/ Wait until the download is done<br \/>\n\t\tyield return download;<\/p>\n<p>\t\tif (download.error != null) {<br \/>\n\t\t\tDebug.Log (download.error);<br \/>\n\t\t\tprint (\"Error downloading: \" + download.error);<\/p>\n<p>\t\t} else {<br \/>\n\t\t\tprint (\"Sent\");<\/p>\n<p>\t\t}<\/p>\n<p>\t}<br \/>\n<\/code><\/p>\n<p>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<br \/>\n<code><br \/>\nStartCoroutine (sendIt ());<br \/>\n<\/code><br \/>\nAs most of my quick unity3d pieces had been in .js this StartCoroutine was not as obvious, though it is in the Unity docs.<br \/>\nThe URL I call has some PHP that gets at the form elements, but we are in normal web territory then.<br \/>\n<code><br \/>\n$somedata = $_POST[\"data1\"];<br \/>\n$somescore = $_POST[\"userscore\"];<br \/>\n<\/code><\/p>\n<p>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. <\/p>\n<iframe src=\"http:\/\/www.facebook.com\/plugins\/like.php?href=https%3A%2F%2Fwww.feedingedge.co.uk%2Fblog%2F2011%2F03%2F09%2Fbrowser-to-unity3d-communication-and-back-again%2F&amp;layout=standard&amp;show_faces=true&amp;width=450&amp;action=like&amp;colorscheme=light&amp;height=80\" scrolling=\"no\" frameborder=\"0\" style=\"border:none; overflow:hidden; width:450px; height:80px;\" allowTransparency=\"true\"><\/iframe><div name=\"googleone_share_1\" style=\"position:relative;z-index:5;float: right; margin-left: 10px;\"><g:plusone size=\"tall\" count=\"1\" href=\"https:\/\/www.feedingedge.co.uk\/blog\/2011\/03\/09\/browser-to-unity3d-communication-and-back-again\/\"><\/g:plusone><\/div>","protected":false},"excerpt":{"rendered":"<p>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&#8217;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<br \/>\n            <span class=\"excerpt-readmore\"><a class=\"more-link\" href=\"https:\/\/www.feedingedge.co.uk\/blog\/2011\/03\/09\/browser-to-unity3d-communication-and-back-again\/\"><\/a><\/span><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[232,46],"tags":[281,207],"class_list":["post-1119","post","type-post","status-publish","format-standard","hentry","category-technical","category-unity3d","tag-communication","tag-drupal"],"_links":{"self":[{"href":"https:\/\/www.feedingedge.co.uk\/blog\/wp-json\/wp\/v2\/posts\/1119","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.feedingedge.co.uk\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.feedingedge.co.uk\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.feedingedge.co.uk\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.feedingedge.co.uk\/blog\/wp-json\/wp\/v2\/comments?post=1119"}],"version-history":[{"count":4,"href":"https:\/\/www.feedingedge.co.uk\/blog\/wp-json\/wp\/v2\/posts\/1119\/revisions"}],"predecessor-version":[{"id":1146,"href":"https:\/\/www.feedingedge.co.uk\/blog\/wp-json\/wp\/v2\/posts\/1119\/revisions\/1146"}],"wp:attachment":[{"href":"https:\/\/www.feedingedge.co.uk\/blog\/wp-json\/wp\/v2\/media?parent=1119"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.feedingedge.co.uk\/blog\/wp-json\/wp\/v2\/categories?post=1119"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.feedingedge.co.uk\/blog\/wp-json\/wp\/v2\/tags?post=1119"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}