So, why can’t I just add a service reference and use that?
Well, you can, and in VS it will build, but, Unity3D won’t have a clue what you are trying to reference..What helped me find the solution I came to?
As you do, I had a mooch on google, and came across a number of post and cross posts that pointed to this method of accessing a web service in Unity. For some reason, when I used this method, Unity3D would complain about the System.ServiceModel namespace, so, I thought, after finding this link saying I can just drop an assembly in and it gets picked up by Unity3D, I dragged and drop System.ServiceModel and System.Runtime.Serialization into my assets script folder. All this seemed to do was throw up another issue, with the HTTP binding. The assemblies I was adding were .NET 3.0, as I now know, Unity3D is really only compliant with 2.0, though I am sure I read somewhere that it’s a bit of a mix between 2.0 and 3.5, what ever the case, it didn’t like me assembles. In the original post I found it mentioned moving the assemblies to the mono folder, naturally I ignored this, I was not using mono, but, it gave me the idea to start looking around the Unity3D mono installation, and I found a set of C# assemblies in there, two of which are the ones I wanted, so, in an act of desperation, I copied those two assemblies over into my assets script folder….and it only bloody worked!How am I doing it now?
So, create your WCF service as you would normally, I am using .NET4.0 for mine. Before you do anything else, create a WebClient folder in your script folder, I do this just to keep it separate, you could just drop it anywhere in your assets folder I guess.As in the original post describing how to do this I use svcutil to build the proxy class for my Unity3d scripts to use, I created a very simple cmd file that I can run for this, before you run it, make sure your service is running, or it wont be able to build it.
cd "f:\development\unity\killercore\webservice"
cls
svcutil -out:F:\Development\Unity\KillerCore\Assets\Scripts\WebClient\KillerCoreWebService.cs http://localhost:9997/KillerCoreWebService.svc?wsdl
copy "C:\Program Files (x86)\Unity\Editor\Data\Mono\lib\mono\2.0\System.Runtime.Serialization.dll" "F:\Development\Unity\KillerCore\Assets\Scripts\WebClient\System.Runtime.Serialization.dll"
copy "C:\Program Files (x86)\Unity\Editor\Data\Mono\lib\mono\2.0\System.ServiceModel.dll" "F:\Development\Unity\KillerCore\Assets\Scripts\WebClient\System.ServiceModel.dll"
cls
svcutil -out:F:\Development\Unity\KillerCore\Assets\Scripts\WebClient\KillerCoreWebService.cs http://localhost:9997/KillerCoreWebService.svc?wsdl
copy "C:\Program Files (x86)\Unity\Editor\Data\Mono\lib\mono\2.0\System.Runtime.Serialization.dll" "F:\Development\Unity\KillerCore\Assets\Scripts\WebClient\System.Runtime.Serialization.dll"
copy "C:\Program Files (x86)\Unity\Editor\Data\Mono\lib\mono\2.0\System.ServiceModel.dll" "F:\Development\Unity\KillerCore\Assets\Scripts\WebClient\System.ServiceModel.dll"
IMPORTANT: Only run this cmd in a Visual Studio Command prompt.
As you can see it copies my resulting code into my script folder, it then also copies the mono assemblies I need into that folder too. Switch back to Unity3D and it will load the new cs script and dll’s
And that is pretty much that, I can now access my WCF web service from with in my Unity3D game.
KillerCoreWebService Call
My very simple service has one method at the moment called GetHighScoreTable, and for the sake of testing looks like this:
public HighScoreResponse GetHighScoreTable()
{
HighScoreResponse hst = new HighScoreResponse();
for (int x = 0; x < 10; x++)
hst.HighScoreTable.Add(new HighScoreEntity(string.Format("High Score {0}", x + 1), (x + 1 * 501).ToString()));
return hst;
}
{
HighScoreResponse hst = new HighScoreResponse();
for (int x = 0; x < 10; x++)
hst.HighScoreTable.Add(new HighScoreEntity(string.Format("High Score {0}", x + 1), (x + 1 * 501).ToString()));
return hst;
}
Client side use of the Web Service
I have a globals script that I use to hold stuff I want to use all over the place, so, the first thing I need is a client object to connect to the service, like this
static KillerCoreWebServiceClient client = new KillerCoreWebServiceClient(new BasicHttpBinding(BasicHttpSecurityMode.None), new EndpointAddress("http://localhost:9997/KillerCoreWebService.svc"));
public static List<HighScoreEntity> GetHighScores()
{
HighScoreResponse response = client.GetHighScoreTable();
return response.HighScoreTable.ToList();
}
{
HighScoreResponse response = client.GetHighScoreTable();
return response.HighScoreTable.ToList();
}
if (GUI.Button(new Rect(0, 0, 100, 50), "Get Highscores"))
{
scores = Globals.GetHighScores();
}
if (scores.Count > 0)
{
GUI.Label(new Rect(10, 110, 100, 20), string.Format("{0} Records", scores.Count));
int cnt = 0;
foreach (HighScoreEntity score in scores)
{
cnt++;
GUI.Label(new Rect(10, 110 + (cnt * 20), 100, 20), string.Format("{0} - {1}", score.Name, score.Score));
}
}
{
scores = Globals.GetHighScores();
}
if (scores.Count > 0)
{
GUI.Label(new Rect(10, 110, 100, 20), string.Format("{0} Records", scores.Count));
int cnt = 0;
foreach (HighScoreEntity score in scores)
{
cnt++;
GUI.Label(new Rect(10, 110 + (cnt * 20), 100, 20), string.Format("{0} - {1}", score.Name, score.Score));
}
}
So, after all my moaning and whinging, it turned out not to be that difficult to set up Unity3D so it can access a WCF web service. I hope this helps make your life a bit easier integrating WCF services into your Unity3D projects. If you find a better way, or have issues with this method, then let me know.
[UPDATE]
Tested this for the Web player and it does not work, I guess just the full executable version, if I do need WS ill end up having to write a post/get class to pull stuff back from a server, unless Unity3D gets an update to the .NET framework I guess.
[/UPDATE]
Hi Charles, wouldn't it be easier to implement a REST service and use the native WWW class from Unity3D
ReplyDeleteIf you check in this article, it demonstrates getting data from a REST service for use in Unity.
http://through-the-interface.typepad.com/through_the_interface/2012/04/calling-a-web-service-from-a-unity3d-scene.html
The WWW class also supports POST as well.
http://docs.unity3d.com/Documentation/ScriptReference/WWW.html
An added benefit is that since the WWW class is native to Unity, you don't need to worry about all the cross platform issues as well
Yes, we discussed this on the Unity FB group, and that is indeed one way to go about it, and at the moment as Unity3D does not fully support WCF that would be the way to go, as you can probably see in my [UPDATE/] section at the bottom.
DeleteIt seems a step backwards to have to use REST, so I am hoping for an update to it WCF could be used in the web player too. But, in the mean time, I can now at least use WCF in a windows deployment :D better than nothing I guess..
Unfortunately, in current versions of Unity, this method does not seem to work any longer :(
Deletehttp://forum.unity3d.com/threads/invalid-il-code-when-consuming-webservices.296151/#post-1978548
Not tried it, that's a shame, thanks for letting me know though mate :)
Delete