uServer

uServer is a standalone library that mocks the Unity engine, enabling you to e.g. develop an external lightweight .NET server application that shares your Unity code. Or, you can use it to develop standalone tests - possibilities are plenty. Even though our other products do not always have standalone alternatives, such as uLink, uServer makes it possible to run them and many other Unity libraries outside Unity. On Windows, uServer also means that you can use the full power of Microsoft Visual Studio for debugging and profiling your code. You may of course also use uServer in Mono applications, using any Mono version of your choice.

Please see the section for API support to see which functionality of the Unity engine is fully available, what is only stubbed, and what is not currently available.

Getting Started using Unity Editor

You should first import the uServer package into your project. Then you can just build the selected scenes in build settings using the menu File/Build for uServer. You should also make sure that your API Compatibility setting in player settings is set to .NET 2.0 and not the subset, otherwise the build process will not work. The built application will be a _Data folder and a .exe console application which can read the data files and executes the game like a normal unity player. All scene objects, levels, prefabs and script orders are correctly available and will work as expected. The data files created can be used by your own uServer based player codes as well. Before initializing the engine, you can let it know of a path for a data folder and ask it to load the data from there and then you can start the first level at engine startup or do whatever you want with the loaded scenes and prefabs.

Getting Started with uServer as a library in your own code

To use uServer as a library you must attach it as a reference to your Visual Studio project. For emulation reasons, the uServer .DLL is called UnityEngine.dll, and can be found in the uServer distribution. Once referenced, Unity as well as uServer-specific APIs will become available through the UnityEngine namespace.

The main class that controls uServer execution is UnityEngine.EngineCore; use its static methods to configure and start the engine. Before doing anything else (including calling Unity’s own APIs), first you must call EngineCore.Initialize().

uServer has additional APIs to perform tasks that are manual in Unity, such as adding scenes and configuring script execution order (You don't need to do these tasks manually when using the editor plugin). You can add “scenes” to the build list using the EngineCore.AddScene(string levelName, Action) method to register handler delgates that will be run upon the corresponding Application.LoadLevel(). The reason, aside from mocking Application.LoadLevel calls, is to precisely emulate the callback order in Unity for level loading. Similarly you may precisely control the script execution order by using EngineCore.AddScriptOrder(int order, type scriptType) method.

The GameObject and prefab system from Unity is more or less the same, with some minor differences. To directly create a prefab, use the GameObject(string, bool isPrefab) constructor overload, you may then use regular GameObject.AddComponent methods to modify it. uServer distinguishes between level load and regular running - if you’re loading a level you need to use GameObject.AddComponentInScene if contsructing a GameObject directly without a prefab.

A simple example to demonstrate initialization, scenes, objects and prefabs:

class Program
{
        static void Main(string[] args)
        {
                //Initializes the engine. runs it for three seconds and then shuts it down.
                //Demonstrates a simulated loaded level load, and prefab and resource creation.
                EngineCore.dataFolderPath = "";
                EngineCore.readLevelsFromFile = false;  //we don't want to read unity editor built levels.
                EngineCore.Initialize();
                EngineCore.AddScriptOrder(100, typeof(MyScript));
                EngineCore.AddScene("hello_world", LoadHelloWorldLevel);

                var prefab = new GameObject("MyPrefab", true);
                prefab.AddComponent<Rigidbody>();
                prefab.AddComponent<MyScript>();
                EngineCore.resourceManager.AddResource("Useless.prefab", prefab);

                Application.LoadLevel("hello_world");

                EngineCore.GameMainLoopForSeconds(3);
                EngineCore.Shutdown(); //to free up static resources and close log file
        }

        static void LoadHelloWorldLevel()
        {
                var prefab = Resources.Load("Useless.prefab") as GameObject;
                GameObject.Instantiate(prefab);

                //constructs game object directly
                var o = new GameObject("MyObject");
                o.AddComponentInScene<MyScript>();
        }
}

class MyScript : MonoBehaviour
{
        IEnumerator Start()
        {
                Console.WriteLine("Created useless object!");

                yield return new WaitForSeconds(1);
                //constructs game object directly
                var o = new GameObject("MyObject");
                o.AddComponent<MyScript>();
        }
}

Running and shutting down the engine

In the EngineCore class there are several Run-methods, that you may call after having called Initialize:

  • RunForever runs the engine until it’s stopped by Application.Quit or some other event like console application signal handlers or an unhandled exception (crash). This is a “fire and forget” method.
  • RunForSeconds runs the engine for the specified number of wall clock seconds.
  • RunForFrames runs the engine the specified number of frames.
  • RunForOneFrame only runs the engine for one frame.

All run methods other than RunForEver don’t call OnApplicationQuit on all game objects when returning. You should call EngineCore.FinishRunning() after manually running the engine through RunXXX to properly simulate Unity’s exit behavior, if desired.

After you’ve run the engine through one of these methods you may shutdown the engine and let the garbage collector free engine memory through EngineCore.ShutDown() method. It is not necessary to call this method before re-initializing the engine for another run using EngineCore.Initialize(), but if you want to leave it uninitialized without holding onto resources (including log files) you should explicitly call EngineCore.ShutDown.

Creating prefabs

To create prefabs (which are not game objects. but rather “blueprints” for game objects), you should use the GameObject(string, bool isPrefab) constructor overload, which when the second argument is true creates a prefab rather than a GameObject in the scene. After constructing the prefab, you can call regular GameObject.AddComponent and GameObject.GetComponent methods on it to initialize, including setting properties.

To instantiate the prefab into an actual GameObject instance, use GameObject.Instantiate.

Resources folder

Loading resources is no different from Unity (e.g. you may use Resources.Load) but there is not yet support for loading Unity resource files directly from uServer, and you must set up prefab references yourself using EngineCore.resourceManager. This enables you to mock the Resources folder.

Creating scenes

If you don't load your scenes from files built by the editor plugin, then you have to code them or ignore the concepts of scenes altogether. No scene is loaded by default, unlike in Unity (for higher control). You don’t have to use scenes, but it can be useful to exactly replicate Unity’s behavior in tests, or for interoperability with level loading code. You can set EngineCore.dataFolderPath and EngineCore.readLevelsFromFile to load the contents of a data folder created by the uServer editor plugin but as said before it's totally optional. The descriptions below assume you want to create levels in code.

To be able to load levels using Application.LoadLevel(), you can use the EngineCore.AddScene(string levelName, Action) method. This registers a scene handling delegate making the level “loadable” by index or name, as if you had added levels through the build list inside the Unity Editor. The delegate you pass to EngineCore.AddScene should only create and setup GameObjects, because this is what Unity’s level loading would do. You can of course place other code there, at the expense of behavior emulation accuracy.

The GameObject.AddComponent methods have an overload called GameObject.AddComponentInScene which should be used in scene creation code. This method does not run OnEnable and Awake directly, and instead queues them to be run after scene loading has finished, corresponding to Unity’s scene load behavior. If you use AddComponent, you risk uninitialized references being used from OnEnable and Awake in cases where Unity would already have fully loaded the level.