To summarize, we do all of our development (debugging) in Visual Studio. By using Remoting Unity can call the methods needed to pass information from our servers to the Unity game server thus limiting Unity development to Unity, and game logic to VS/.NET.
First off, the call for the client method: SampleClient2.Main2 ();
The client code. This creates a connection to the server and fetches the object ‘testclass2’. The client (unity) then runs the testclass2 object on the server (Visual Studio/.Net)
For testing, I simply ran the server in VS debugger. It would not compile under Unity because of Internal Compiler errors BUT
it would run in the Mono debugger, just not compile.
So you could test this out by compiling the client and running the server in the Mono/debugger.
I wish you all the best of luck. Don’t hestitate to ask questions.
Addendum: You will also need to find and copy the following dlls. Create a folder under your asset folder called “Plugins” and copy the following from your Mono version that was installed with Untiy. Do NOT fetch anything from your Windows directory:
System.Runtime.Remoting.dll
System.Runtime.Serialization.dll
using UnityEngine;
using System.Collections;
using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Runtime.Remoting.Channels.Http;
using System.IO;
// using System.Collections; // REQUIRED FOR .NET
using System.Runtime.Serialization.Formatters;
using System.Threading;
public class SampleClient2: MonoBehaviour
{
public static void Main2() //string [] args)
{
// Create a channel for communicating w/ the remote object
// Notice no port is specified on the client
TcpChannel chan = new TcpChannel();
// Unity may hang here. If so, make sure that the channel (port) is not already registered.
// Also, if you do not name your channels, the default is 'tcp'. If you attempt to register more than one channel without
// naming them you will get a duplicate channel.
ChannelServices.RegisterChannel(chan, false); // the channel 'tcp' is already registered error
// Create an instance of the remote object
testclass2 obj= null;
// Crashes here tend to be that the server is not up and waiting for a call.
try {
obj = (testclass2) Activator.GetObject(
typeof(testclass2),
"tcp://localhost:8020/GetCount" );
}
catch(Exception ce)
{
Debug.Log("Abort in main2 trying to fetch object " + ce.Message);
//Console.WriteLine(ce.Message);
}
// At this point you can use the object.
int i = (testclass2)obj).GetCount();
// While this code should work and I will try to get it to work somehow, the following 'if' statement causes
// Unity/Mono to crash.
// if( obj.Equals(null) )
// {
// System.Console.WriteLine("Error: unable to locate server");
// }
// else
// {
// Call your remote method. Warning. If you have your server app and this client in the same runtime you may not
// know if you truly are calling the remote method or the local as obj is declared as (testclass2).
// Therefore, "build and run" your server in a separate executable.
Debug.Log ("count is " + obj.GetCount());
// The following error pops up for unknown reasons at unknown times. :(
// Nothing had changed between code runs, Unity was just crashed and was restarted.
// Another strange Unity/Mono error at times is this one:
// Mono.Debugger.Soft.VMDisconnectedException: Exception of type 'Mono.Debugger.Soft.VMDisconnectedException' was thrown.
// at Mono.Debugger.Soft.Connection.SendReceive(CommandSet command_set, Int32 command, PacketWriter packet) in c:\BuildAgent\work\9ffd76bfa3f1a926\monodevelop\main\contrib\Mono.Debugger.Soft\Mono.Debugger.Soft\Connection.cs:line 1451
// at Mono.Debugger.Soft.Connection.VM_GetThreads() in c:\BuildAgent\work\9ffd76bfa3f1a926\monodevelop\main\contrib\Mono.Debugger.Soft\Mono.Debugger.Soft\Connection.cs:line 1542
// at Mono.Debugger.Soft.VirtualMachine.GetThreads() in c:\BuildAgent\work\9ffd76bfa3f1a926\monodevelop\main\contrib\Mono.Debugger.Soft\Mono.Debugger.Soft\VirtualMachine.cs:line 175
// at Mono.Debugging.Soft.SoftDebuggerSession.GetThread(Int64 processId, Int64 threadId) in c:\BuildAgent\work\9ffd76bfa3f1a926\monodevelop\main\src\addins\MonoDevelop.Debugger.Soft\Mono.Debugging.Soft\SoftDebuggerSession.cs:line 727
// at Mono.Debugging.Soft.SoftDebuggerSession.OnGetThreadBacktrace(Int64 processId, Int64 threadId) in c:\BuildAgent\work\9ffd76bfa3f1a926\monodevelop\main\src\addins\MonoDevelop.Debugger.Soft\Mono.Debugging.Soft\SoftDebuggerSession.cs:line 700
// at Mono.Debugging.Client.DebuggerSession.GetBacktrace(Int64 processId, Int64 threadId) in c:\BuildAgent\work\9ffd76bfa3f1a926\monodevelop\main\src\core\Mono.Debugging\Mono.Debugging.Client\DebuggerSession.cs:line 947
// at Mono.Debugging.Client.ThreadInfo.get_Backtrace() in c:\BuildAgent\work\9ffd76bfa3f1a926\monodevelop\main\src\core\Mono.Debugging\Mono.Debugging.Client\ThreadInfo.cs:line 79
// at Mono.Debugging.Client.ThreadInfo.get_Location() in c:\BuildAgent\work\9ffd76bfa3f1a926\monodevelop\main\src\core\Mono.Debugging\Mono.Debugging.Client\ThreadInfo.cs:line 64
// at MonoDevelop.Debugger.ThreadsPad.AppendThreads(TreeIter it, ProcessInfo p) in c:\BuildAgent\work\9ffd76bfa3f1a926\monodevelop\main\src\addins\MonoDevelop.Debugger\MonoDevelop.Debugger\ThreadsPad.cs:line 176
// at MonoDevelop.Debugger.ThreadsPad.UpdateDisplay() in c:\BuildAgent\work\9ffd76bfa3f1a926\monodevelop\main\src\addins\MonoDevelop.Debugger\MonoDevelop.Debugger\ThreadsPad.cs:line 146
//// }
}
}
The SERVER CODE:
[//using UnityEngine;
//using System.Collections;
using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Runtime.Remoting.Channels.Http;
using System.IO;
using System.Collections;
using System.Runtime.Serialization.Formatters;
using System.Threading;
// This is the server. Start up the channel to listen and for testing I just go
// into a while(true) loop.
// This was built and executed on Visual Studio 2013 as Unity/Mono could NOT compile this
// due to internal compiler errors that were of no help trying to debug them.
public class SampleServer2 // : MonoBehaviour
{
public static void Main()
{
// Create an instance of a channel
int tcpPort = 8020;
// ------------------------------------------------------------
BinaryServerFormatterSinkProvider serverProv =
new BinaryServerFormatterSinkProvider();
serverProv.TypeFilterLevel = TypeFilterLevel.Full;
//UNITY/MONO debugging hangs if the following code is included. This script was originally provided
// by others but would not run without tweaking it.
// RemotingConfiguration.CustomErrorsMode = CustomErrorsModes.Off;
IDictionary propBag = new Hashtable();
serverProv.TypeFilterLevel = TypeFilterLevel.Full;
// -----------------------------------------
// I did NOT try security so it may or may not work.
bool isSecure = false; // [true/false];
propBag["port"] = tcpPort;
propBag["typeFilterLevel"] = TypeFilterLevel.Full;
propBag["name"] = "UniqueChannelName"; // here enter unique channel name
if (isSecure) // if you want remoting comm to be secure and encrypted
{
propBag["secure"] = isSecure;
propBag["impersonate"] = false; // change to true to do impersonation
}
// -----------------------------------------
// If you hang/crash here you probably have the channel tied up with another instance of the server or
// program. Also if you have a firewall (Windows 7) you should see a notification asking for permission
// for access.
// You may need to see this link if you have Access Right Problems:
// http://stackoverflow.com/questions/885744/wcf-servicehost-access-rights
TcpChannel tcpChan = new TcpChannel( propBag, null, serverProv);
ChannelServices.RegisterChannel(tcpChan, isSecure);
// Without secure paramete I believe that Mono/Unity croaked again.
//ChannelServices.RegisterChannel(channel);
// Register as an available service with the name GetCount
// Every incoming message is serviced by the same object instance.
RemotingConfiguration.RegisterWellKnownServiceType(
typeof(testclass2),
"GetCount",
WellKnownObjectMode.Singleton );
// keep the program running so that it can answer calls.
while (true)
{ }
}
}