For the past few weeks I’ve been working on integrating Realm Engine into Unity. I started off by working through the steps of launching Realm Engine from within Unity. Originally Realm Engine would start from within a console application called BasicServer. This program would handle most of the basic tasks for start; reading in startup parameters, creating a new realm if one does not exist, loading an existing realm if requested to do so, starting the main game simulation / server process and proceeding from there. When a player would play a single player game we would have the game client launch an instance of BasicServer invisibly in the background with special single player startup parameters and have the client make a local connection to the server. For dedicated server hosting a server admin could either directly launch the BasicServer program or they could utilize a server creation / management / launching tool we had created (generally called RealmEngine.Server.Configuration.UI). Either way the game server would always start up inside of the BasicServer console app and generally be invisible in the background.
The first step in integrating Realm Engine into Unity was to replicate some of the things that BasicServer handled for us; primarily reading in startup parameters, creating/loading a realm and instantiating the main GameServer class on a separate thread and starting the GameServer. Since we’re now starting up our server process from within Unity itself (with the goal of having communication between Unity and Realm Engine) we needed to make it clear within our Unity code whether we’re acting as a client or server. Additionally if we’re acting as a server we need to transition between a few different scenes in Unity (for example, skipping the main menu scene where the player can log in, change game options, connect to a server, create a character and so on).
Getting through these initial stages of integration were fairly easy. The entire integration was not quite as seamless, however. Several immediate issues arose that had varying degrees of difficulty in resolving. For example, we had to streamline how we are dealing with paths to the file system. Previously our code acted under the assumption that assemblies were in the root directory. After integrating into Unity all assemblies moved to the \RealmExplorer_Data\Managed\ directory. If our code expected that we were in the root directory we really needed to look 2 levels up from where we were actually starting to find directories and files we were expecting.
Another issue that came about was a problem with how we get information specific to the game we are dealing with. Since Realm Engine is a generic technology not tied to any specific game we have an interface called IGameInfo. Each game is responsible for creating a class that implements this interface and provides certain common data that various areas of the game use; for example, the name of the game, copyright information and other data to identify each game uniquely. Realm Engine has a concrete class that we can program against to get this information. The class within Realm Engine dynamically (via reflection) looks through the the available assemblies to locate which one contains a class that implements IGameInfo and then loads that data once. While this worked perfectly for our stand alone builds we ran into an issue within Unity where the entire editor would freeze when compiling the game.
After working with Unity’s support staff (not knowing what the exact issue was at the time) they were able to help us determine that some kind of deadlock was occurring during compilation. This ended up being because Unity was in some way inspecting the static properties of the engine-level class which caused it to attempt to dynamically examine other assemblies. With the general information in mind that we were running into a deadlock during compilation from the Unity editor we were able to track down the cause and modify how it worked. Previously we would sort through a specific child directory for .dll files and then do an Assembly.ReflectionOnlyLoadFrom(file) to see if we could find the assembly that had the class we were looking for. If we found the class we would then fully load that assembly, instantiate the class via Activator.CreateInstance(…) and perform our one-time read. We worked around this issue by simply using AppDomain.CurrentDomain.GetAssemblies() to examine already loaded assemblies (which Unity takes care of for us) and finding the type that implements the expected interface. This was a very puzzling issue for several days (in part because there was absolutely no information of any kind in the Unity logs nor any kind of exception, error or anything that we could act on) but it was ultimately resolved.
Finally there were several challenges with handling Realm Engine’s dynamic script compilation from within Unity. Realm Engine (and thus Realm Explorer) has an incredibly powerful scripting system; our scripting system is one of the pillars of our engine technology. When Realm Engine starts up is locates script folders (which can be configured on a per-realm basis), reads in all of the script files, compiles them and then integrates them into the Entity-Component system. Unfortunately the CSharpCodeProvider and VBCodeProvider classes have some implementation issues in Unity. After a lot of testing and research none of the proposed work arounds that others had discovered were desirable. Fortunately an idea I came up with worked without a hitch. Ultimately my solution involved creating a separate compiler executable project and having the Realm Engine process (now hosted within Unity) launch the compiler executable and provide some startup parameters to it. The compiler would then perform the compilation and generate a compiled DLL with a file name and in a location based on instructions from the process requesting the compilation. From there the compiled assemblies could be easily loaded into Unity and the script contents loaded with reflection as per usual.
(By the way, we’re including the vast majority of gameplay-related scripts as raw C# files that users can view, modify and learn from. This will enable motivated players to do things like creating new items, craft recipes, NPCs and more. Players with a little C# or VB .NET programming capability will be able to do much more!)
The process of integrating Realm Engine within Unity ended up having many more obstacles than expected (some of which were quite difficult to resolve) but after working through all of these issues this milestone has been achieved.
I know I’ve been teasing some juicy in-game features (and they’re still coming!) but next time I’m going to talk a little bit about synchronizing calls from Realm Engine into Unity. Getting to this point was one of the major reasons for integrating Realm Engine into Unity in the first place and the end result is extremely satisfying!