Skip to content

Hacking VR into a Unity game

Eusth edited this page Apr 25, 2017 · 4 revisions

CAUTION

Not everything on this page holds true anymore. You may want to start by simply checking out the template project, which does the same as the guide below would tell you and more.


Requirements

  • Visual Studio Community 2015 (or whatever version you prefer)
  • A Unity-based game (4.6+)
  • Some basic C# skills
  • Optional: Git (more precisely, the git command)

Note: because of changes to the code and new Unity versions, this will probably not work out of the box. I will probably release a generic project file that can be downloaded and should more or less work with Unity 5.x projects.

1. Setting up the project

First of all, let's create the base we'll be working on.

  1. Open Visual Studio
  2. Create a new project via File -> New -> Project... 3. Select Class Library for the project type and .NET Framework 3.5 for the target framework (for LINQ) 4. Enter the name of your project 5. Hit OK

Now that we have the project, we're going to install VRGIN.

  1. Go to the directory of your solution (right click on solution -> Open Folder in File Explorer)
  2. If you have Git:
    1. Open a command window in this folder (Shift + RMB, w, Return)
    2. Execute git clone https://github.com/Eusth/VRGIN.git
  3. If you don't have Git:
    1. Download VRGIN (https://github.com/Eusth/VRGIN/archive/master.zip)
    2. Extract it into the solution folder
  4. Switch back to Visual Studio and add the project by right-clicking on your solution and choosing Add -> Existing Project...
  5. In the file picker, change into the folder you cloned earlier and choose either VRGIN.csproj or VRGIN.U46.csproj (use the latter for Unity 4 projects)
  6. Reference the VRGIN project in your own project 7. Right click on References and choose Add References... 8. Check the VRGIN item in the Projects pane 9. Tip: You might also want to reference the UnityEngine.dll while you're at it. The VRGIN has them in the Libs folder 10. Finally, accept the changes with OK

VRGIN is now installed and your project should compile. However, we'll do a final little adjustment for your convenience.

  1. Open the Configuration Manager (Build-> Configuration Manager...)

  2. Click on the current configuration of your project (probably Debug) and choose <New...>

  3. Name it Install and copy settings from Release

  4. Accept by pressing OK and close the configuration manager.

  5. Close your project (right click on your project -> Unload Project) and save any unsaved changes

  6. Open your project file in edit mode (right click on your project -> Edit ____.csproj)

  7. Scroll all the way down and copy & paste the following code above the </Project> closing tag:

{INSTALLDIR} $(InstallDir){GAMENAME}_Data\ $(InstallDir)Plugins\ ``` 8. Replace `{INSTALLDIR}` with the install directory of your target game (where the executable is located) **with a trailing backslash** and `{GAMENAME}` with the name used in the exe and the data directory. 9. Save and close the file 10. Right click on your project -> `Reload Project`

With this change, you can now easily install your VR mod by building the project in the Install configuration

2. Hooking yourself into the game

Now, you'll need a way to inject your code into the game. VRGIN does not come with anything to help you in that respect, but you could use my Illusion Plugin Architecture (IPA) project. It's not very pretty, but it does the job.

Using the IPA

IPA works by injecting itself (IllusionInjector.dll) into the UnityEngine.dll of your game. The injector will then load all plugins found in a Plugins folder that implement the interface defined in IllusionPlugin.dll.

  1. Extract the contents of the IPA archive (https://github.com/Eusth/IPA/releases) into the install directory of your target game
  2. Drag & drop the game exe on IPA.exe
  3. Rename the newly generated [GAME]_Patched.exe to [GAME]VR.exe
  4. Create a new Libs directory under your solution and extract IllusionPlugin.dll into it (optionally, also extract IllusionPlugin.xml for documentation)
  5. Switch to your project and add IllusionPlugin.dll as a reference

3. Implementing VR

This is where things get interesting. At the very least you need three classes:

  • Plugin class that wires everything up and acts as the entry point
  • A context class that lets you configure how VRGIN should do things
  • An interpreter class that provides information what is happening in the game at a give time

Additionally, you can create Actor classes that let you do stuff with the figures in the game, Modes (design your own modes or optimize existing ones), Tools, Settings, etc.

  1. Create a new class and name it whatever you like (e.g. MyVRContext.cs)
  2. Add the following code and adjust the namespace and the class name:
using System;
using UnityEngine;
using VRGIN.Controls.Speech;
using VRGIN.Core;
using VRGIN.Visuals;

namespace MyVRNamespace
{
    class MyVRContext : IVRManagerContext
    {
        DefaultMaterialPalette _Materials;
        VRSettings _Settings;
        public MyVRContext()
        {
            _Materials = new DefaultMaterialPalette();
            _Settings = VRSettings.Load<VRSettings>("vr_settings.xml");
        }

        public bool GUIAlternativeSortingMode
        {
            get
            {
                return false;
            }
        }

        public float GuiFarClipPlane
        {
            get
            {
                return 10000f;
            }
        }

        public string GuiLayer
        {
            get
            {
                return "Default";
            }
        }

        public float GuiNearClipPlane
        {
            get
            {
                return 0.1f;
            }
        }

        public int IgnoreMask
        {
            get
            {
                return 0;
            }
        }

        public string InvisibleLayer
        {
            get
            {
                return "Ignore Raycast";
            }
        }

        public IMaterialPalette Materials
        {
            get
            {
                return _Materials;
            }
        }

        public global::UnityEngine.Color PrimaryColor
        {
            get
            {
                return Color.cyan;
            }
        }

        public VRSettings Settings
        {
            get
            {
                return _Settings;
            }
        }

        public bool SimulateCursor
        {
            get
            {
                return true;
            }
        }

        public string UILayer
        {
            get
            {
                return "UI";
            }
        }

        public int UILayerMask
        {
            get
            {
                return LayerMask.GetMask(UILayer);
            }
        }

        public float UnitToMeter
        {
            get
            {
                return 1f;
            }
        }

        public Type VoiceCommandType
        {
            get
            {
                return typeof(VoiceCommand);
            }
        }
    }
}

You might have to adjust the properties for your project. Refer to the source for explanations and take a look at sample implementation (Honey Select, Play Club).

Now that your context class is created, we'll have to create a simple interpreter class.

  1. Create a new class and name it whatever you like (e.g. MyVRInterpreter.cs)
  2. Add the following code and adjust the namespace and the class name:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using VRGIN.Core;

namespace MyVRNamespace
{
    class MyVRInterpreter : GameInterpreter
    {
        public override IEnumerable<IActor> Actors
        {
            get
            {
                yield break;
            }
        }
    }
}

Now all that's missing is the actual plugin class.

  1. Create a new class and name it whatever you like (e.g. MyVRPlugin.cs)
  2. Add the following code and adjust the namespace and the class name:
using IllusionPlugin;
using System;
using VRGIN.Core;
using VRGIN.Modes;

namespace MyVRNamespace
{
    class MyVRPlugin : IPlugin
    {
        public string Name
        {
            get
            {
                return "My Kick-Ass VR Plugin";
            }
        }

        public string Version
        {
            get
            {
                return "1.0";
            }
        }
        
        public void OnApplicationStart()
        {
            if (Environment.CommandLine.Contains("--vr"))
            {
                var context = new MyVRContext();
                VRManager.Create<MyVRInterpreter>(context);
                VR.Manager.SetMode<SeatedMode>();
                //VR.Manager.SetMode<StandingMode>();
            }
        }


#region Unused
        public void OnApplicationQuit() {}
        public void OnFixedUpdate() { }
        public void OnLevelWasInitialized(int level) { }
        public void OnLevelWasLoaded(int level) { }
        public void OnUpdate() { }
#endregion

    }
}

Et voilà, you're done. Build the project with the Install configuration and run the game with your VR exe.

Common pitfalls

It's possible that the game doesn't come with all libraries that are required. Particularly, this could be the case for System.Xml.dll and System.Xml.Linq.dll. In such cases, simply add the corresponding version of said DLL to the Managed folder in the Data folder of the game. You can usually get the DLLs from a Unity installation.

In general, when things don't work, take a look at the vr.log or start the game with the --verbose flag.