subscribe via rss
6 Sep 2010

[Unify Wiki] Webservices In Unity

Author: Unity3D News Pipe | Filed under: ByDesign Games, Technology

Summary:



This will show you how to set up webservices and how to consume these services, and services from 3rd partys, from within Unity. It will also expand into using the ''Windows Communication Framework'' (''WCF'') which adds a lot of communication options, like JSON, built-in security and communicating directly over TCP/IP.

All code is written in C# on both the server and the client side.

== Introduction ==

Using webservices you can talk to your webserver from within Unity using [http://en.wikipedia.org/wiki/SOAP SOAP].

By using ''System.Web.Services'', or ''System.Servicemodel'' for ''WCF'', as well as some Mono utilities - ''wsdl'' and ''svcutil'' for generating service descriptions and ''xsp'' as a development webserver, we can call the webserver functions directly from within our clients and even receive complex .Net objects as a response.

Unfortunately, as an oversight (I hope), this is currently not possible from within the webplayer - only in standalone builds.

== Requirements ==

All of the below is written with the assumption that you have ''Unity 3'' installed, aswell as a separate installation of ''Mono 2.7.6''. To host the webservices in a production environment you should use ''Apache'' and ''mod_mono'' or ''Microsoft IIS'' - whichever you prefer.

I have only tested this on Windows, but there should be nothing very system specific here.

== Using ASP.NET services (.asmx) ==

We will start by using the webservices from System.Web.Services, as these are the simplest. It only gives us basic SOAP but for many cases this might be sufficient.

On the server side we will use what ASP.NET calls .asmx files, which contain the definition of the service. We will then use the Mono utility ''wsdl'' to automatically generate a source code file for the client.

=== Setting up the project ===

Create a new project and name it '''''asmxtest'''''. In your Assets folder, create a new folder and rename it to <tt>Plugins</tt>. To access the webservices we need some assemblies from Mono. In your Unity installation folder, go to the directory <tt>Editor/Data/Mono/lib/mono/2.0</tt> and copy these two files to your new <tt>Plugins</tt> folder:

* <tt>System.Web.dll</tt>
* <tt>System.Web.Services.dll</tt>

In Unity, create a new scene. Inside your Assets folder, create a new folder and name it <tt>WebClient</tt>. Inside this folder, create a new C# script named <tt>ClientObject.cs</tt>. Add an Empty Gameobject and rename it to WebClient. Add the ClientObject.cs to the WebClient object, and save the scene.

Also, in your '''project folder''' (''not'' your Assets folder) create a new folder and name it <tt>WebServer</tt>. This will be where you place your webserver files - you can of course place it anywhere, but I prefer to keep it within the project while developing.

=== The webserver ===

Inside the WebServer directory, create the file <tt>MyService.asmx</tt>. Also create a directory named <tt>App_Code</tt> and inside it a file named <tt>MyService.asmx.cs</tt>.

The <tt>App_Code</tt> directory is where you place all the code for the webservices, while the root only holds the .asmx description files. Later, when you are ready for production, the .cs files can be compiled and placed inside a ''/bin'' directory instead.

<tt>MyService.asmx</tt> is the service description file. Here we define the service language (C#), and the class to use - in our case this is the class <tt>WebService</tt>.

In our code file, <tt>MyService.asmx.cs</tt>, we define the class ''WebService'', and add the method ''Add'' which will simply add two integers and return the result. Note the decorators: <tt>[WebService]</tt> defines this class as a web-service, and <tt>[WebMethod]</tt> makes the method availiable to call from the client. Methods can be defined in this class without the <tt>[WebMethod]</tt> decorator - they will then not be callable by SOAP.

==== MyService.asmx ====

<csharp><%@ WebService Language="C#" Class="MyService"%></csharp>


==== MyService.asmx.cs ====

<csharp>using System;
using System.Web.Services;

[WebService (Namespace = "http://tempuri.org/MyService")] // tempuri.org is the default, you should change this
public class MyService
{
[WebMethod]
public int Add(int a, int b)
{
return a+b;
}
}</csharp>


=== Testing the server ===

Now, lets test the server. Start a command shell (''cmd'') and change to the webserver directory. We will now use ''xsp'' to serve the pages, ''xsp'' can be found in your Mono installation directory (ex. ''C:\Program Files\Mono-2.6.7\bin''). I reccomend you put this directory in your path.

Start the webserver from the command prompt:

<pre>> xsp</pre>

By default it will host the current directory on port 8080, so to see your web-server in action, start up a browser and point it to http://localhost:8080/MyService.asmx - Wohoo! It works!

You can now see all methods provided by this service, and even test them using the builtin web interface.

=== Consuming the service ===

Keep the webserver running for now, we will now automatically create a class for the client to use with the ''wsdl'' utility, which is also included in the Mono installation.

First, lets take a look at the system description that the server generates for this utility, point your browser to http://localhost:8080/MyService.asmx?wsdl - this will give you an xml file with the web-service description. It is this information that the ''wsdl'' utility uses to generate a C# file.

So lets get started, open up a new command prompt and change to your Unity project folder (''asmxtest/Assets/WebClient''). Run ''wsdl'' as follows:

<pre>> wsdl -out:MyService.cs http://localhost:8080/MyService.asmx?wsdl</pre>

This will create a file called <tt>MyService.cs</tt> which includes everything you need to call the webservice from within your Unity project (to see the parameters you can pass to the ''wsdl'' utility, run it without any arguments).

Open the file <tt>MyService.cs</tt> and take a look, but don't change anything.

Now, lets try consuming this service from within Unity. Remember the <tt>ClientObject.cs</tt> file you created earlier? Open it up and enter the following code.

==== ClientObject.cs ====

<csharp>using UnityEngine;
using System;
using System.Collections;

public class ClientObject : MonoBehaviour
{
void Start()
{
MyService service = new MyService();
int n = service.Add(2,3);
Debug.Log(n);
}
}</csharp>


You can now try to play the scene from Unity - keep an eye on the console.

What we do here is create a service object which is defined in the <tt>MyService.cs</tt> file, and we simply call the ''Add'' method on this object. This will connect to our webserver, call the function there, and return us the result. Magic!

I'm not going to go any further in how to write the webservices, but you should be able to expand on this easily, by for example adding database access and whatever you'd like.

There are also publically availiable webservices on the web that you can use, for example check out http://www.service-repository.com/

== Using WCF ==

Lets move on to try using web services with the Windows Communication Framework. We can do the same things here as with the previous, but we get a lot more options - we can even write our service servers using sockets.

=== Setting up the project ===

Lets start again by creating an empty project, this time naming it '''''wcftest'''''. We will need some Mono assemblies for this as well, so create a <tt>Plugins</tt> folder inside your assets directory. Copy the following files from the Unity installation directory <tt>Editor/Data/Mono/lib/mono/2.0</tt>:

* System.Runtime.Serialization.dll
* System.ServiceModel.dll

In Unity, create a new scene. Inside your Assets folder, create a new folder and name it <tt>WebClient</tt>. Inside this folder, create a new C# script named <tt>ClientObject.cs</tt>. Add an Empty Gameobject and rename it to WebClient. Add the ClientObject.cs to the WebClient object, and save the scene.

Again create a directory for the webserver in the project folder ('''not''' the Assets folder) naming it <tt>WebServer</tt>.

We will also need to change the Mono compatibility setting in Unity. Go to your '''Player Settings''' (Edit->Project Settings->Player) and set the "API compatibility layer" to ".NET 2.0" (not Subset).

=== The webserver ===

The first thing we will need here is a config file, so create an empty file and name it <tt>web.config</tt>. Copy the below into the config file

==== web.config ====

<pre><configuration>
<system.serviceModel>
<services>
<service name="WebService" behaviorConfiguration="b">
<endpoint binding="basicHttpBinding" contract="IWebService" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="b">
<serviceMetadata httpGetEnabled="true" httpGetUrl="wsdl" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration></pre>


We will also need a service description file. This is similar to the '''.asmx''' file from above, but this time we'll name it <tt>MyService.svc</tt>. Notice that we define a '''Service''' and not a '''Class'''.

==== MyService.svc ====

<csharp><%@ServiceHost language="C#" Service="WebService"%></csharp>


Again for Mono to find the actual code, we need a directory named <tt>App_Code</tt>. We'll do it the "right way" and define a service interface, and then an implementation.

For the service interface, create a file named <tt>IMyService.cs</tt> in the <tt>App_Code</tt> directory with the following contents:

==== IMyService.cs ====

<csharp>using System;
using System.Collections;
using System.ServiceModel;

[ServiceContract]
public interface IMyService
{
[OperationContract]
int Add(int n1, int n2);
}</csharp>


You will notice we use decorators like we did with the .asmx implementation, however the names are a bit different. <tt>[ServiceContract]</tt> defines this interface as a service contract and <tt>[OperationContract]</tt> defines operations that should be part of this service contract.

Lets go on and create an implementation from this class, we will do this in the file <tt>MyService.cs</tt>:

==== MyService.cs ====

<csharp>using System;
using System.Collections;
using System.ServiceModel;

public class MyService : IMyService
{
public int Add(int n1, int n2)
{
return n1+n1;
}
}</csharp>


We will leave it at this for now, as you see we have only implemented the same service we did in .asmx. You can now start the webserver, open a command prompt, change to the webserver directory and run xsp

<pre>> xsp</pre>

=== Consuming the service ===

Unfortunately we don't get a nice webinterface for testing our service when using WCF as we do with asmx. Lets instead test it by writing a client in Unity.

We'll start by autogenerating some code with '''svcutil'''. Open a command prompt and run the command:

<pre>> svcutil -out:MyServiceClient.cs http://localhost:8080/MyService.svc/wsdl?wsdl</pre>

You should get a file <tt>MyServiceClient.cs</tt> - copy this to your <tt>Assets/WebClient</tt> directory. You can open this up and take a look if you'd like but you shouldn't need to change it.

Now let's edit the <tt>WebObject.cs</tt> file:

==== WebObject.cs ====

<csharp>using UnityEngine;
using System;
using System.Collections;
using System.ServiceModel;

public class TestObject : MonoBehaviour
{
void Start()
{
MyServiceClient client = new MyService(new BasicHttpBinding(),
new EndpointAddress("http://localhost:8080/MyService.svc"));
int n = client.Add(1,2);
Debug.Log(n);
}
}</csharp>


Play your scene, you should now get the result of the add in the console.

== Webservices in the WebPlayer ==

TODO

=== Apache Thrift ===

See [[Using Apache Thrift Webservices From Unity]]

Windows binaries http://www.bernhardglueck.com/downloads/Thrift.zip

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>