Since Unity Technologies is now closely collaborating with Microsoft, it's relatively easy to set up Visual Studio Code editor to work with Unity Engine. You do get intellisense and advanced debugging capabilities, but you don't get syntax coloration properly like in full Visual Studio. The highlighter in VS Code is not context aware, it does not have semantic highlighting. The highlighting is based on regular expressions, upon which a chosen textMate theme is applied. This means your own types, Unity types, all fields and method calls will simply be white. It also seems roslyn (OSS compiler) already has the required API capability to implement this and it is a matter of time when Code will get it. Well, it's been about a year and we still didn't get it... Even the prettyprint on my site that you can see below has better syntax recognition!

I personally use Visual Studio, but I've found VS Code useful for dealing with code snippets and especially web programming. It seems it was made for the later. Let me also say this solution feels somewhat "hacky". I am sure there are a bunch of ways to be improved, however for my purposes it is enough and this is what I'll show here.

The main idea is: now that C# is separate from the core of VS Code it can be styled independently. The semantics for C# are defined in a file %USERPROFILE%\.vscode\extensions\ms-vscode.csharp-1.3.0\syntaxes\csharp.json, provided you have C# extension installed. It's a json configuration file that you can edit, save and restart Code and the new settings will be applied. Before starting, make sure to back up the original.

The second thing to do is we want all the possible types and their members from Unity. We need to write an editor script. Create an editor class in an Editor forlder and add this method to it.

 

    [MenuItem("VS Code/GetAllMembers")]
    pubic static void GetAllMembers() {
        Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
        IEnumerable types;
        string recognizedClassesPropertiesFields = "";
        string recognizedMethods = "";
        List foundClassesPropertiesFields = new List();
        List foundMethods = new List();

        string[] namespaces = { "UnityEngine", "UnityEditor" };
        for(int i = 0; i < namespaces.Length; i++) {
            types = assemblies.SelectMany(t => t.GetTypes()).Where(t => (t.IsClass || t.IsAnsiClass) && t.Namespace == namespaces[i] && t.IsPublic);

            foreach(Type t in types) {
                recognizedClassesPropertiesFields += t.Name + "|";
                
                MethodInfo[] methodInfos = t.GetMethods(BindingFlags.Public | BindingFlags.Instance);
                foreach(var methodInfo in methodInfos) {
                    string cleanName = methodInfo.Name.Replace("get_", "").Replace("set_", "");
                    if(!foundMethods.Contains(cleanName) && cleanName[0].ToString() == cleanName[0].ToString().ToUpper()) {
                        foundMethods.Add(cleanName);
                        recognizedMethods += cleanName + "|";
                    }
                }

                FieldInfo[] fieldInfos = t.GetFields(BindingFlags.Public | BindingFlags.Instance);
                foreach(var fieldInfo in fieldInfos) {
                    string cleanName = fieldInfo.Name.Replace("get_", "").Replace("set_", "");
                    if(!foundClassesPropertiesFields.Contains(cleanName)) {
                        foundClassesPropertiesFields.Add(cleanName);
                        recognizedClassesPropertiesFields += cleanName + "|";
                    }
                }

                PropertyInfo[] propertiesInfos = t.GetProperties(BindingFlags.Public | BindingFlags.Instance);
                foreach(var propertyInfo in propertiesInfos) {
                    string cleanName = propertyInfo.Name.Replace("get_", "").Replace("set_", "");
                    if(!foundClassesPropertiesFields.Contains(cleanName)) {
                        foundClassesPropertiesFields.Add(cleanName);
                        recognizedClassesPropertiesFields += cleanName + "|";
                    }
                }
            }
        }
        Debug.Log(recognizedClassesPropertiesFields);
        Debug.Log(recognizedMethods);
    }

You run it by clucking VS Code / GetAllMembers from the top menu. Wait a few seconds and 2 long strings will be printed to the console. They are probably too long to be shown at the bottom of the console, so you need to open a log file at %localappdata%\Unity\Editor\Editor.log. Don't open it with VS Code nor notepad, the lines are too long and will possibly freeze the 1st and create line breaks in the 2nd. Use Notepad++, which is vastly superior for editing non-context sensitive configuration files. 

Copy the first line. It represensts all the class names, all the unique properties and fields. Open csharp.json (which you have backed up) also with Notepad++ and somewhere around line 87 there is a key "builtinTypes". Find the sub-key "match" and see all builtin types shown. At the end paste the contents of the first line, before the `)\\b"`, and remove the last |.

Copy the second line. It represents all unique method names. I do this separately because matching for methods is different from classes, fields and properties, and braces will prevent the method from being highlighted. On line 296 find "match" key for all keywords. Paste these at the end of it, before the `)\\b"`, and remove the last |.. Save it and restart VS Code.

What remains is to find a nice VS theme to render this now. I like Dark+ and Son Of Obsidian. 

There are a few drawbacks. First, you'll notice not all methods are found (some in UnityEditor seem to be missing). This didn't bother me much, but it's probably fixable with correcting the reflexion work from above. The second is, when this extension is updated, this file may or may not get overwritten. It's up to you if it's worth it to you to work around this.


If you're finding this article helpful, consider our asset Dialogical on the Unity Asset store for your game dialogues.
 

 


Log In:




Comments (0)