[Solved] Batchmode CLI build: the type or namespace name 'Build' does not exist in the namespace 'UnityEditor'

tldr; If you have a top-level custom asmdef in your Assets folder, you need an Editor asmdef in the Editor folder that only targets the Editor and references any assemblies you use in it.

I’ve solved this during writing this up, so adding it in full for others.

Detail

I want to set the product version number on the command line build (aka batchmode) so that the number can be easily reused by git tag and Steam upload.

In both my attempts, the custom code cannot use the required Editor classes.

Failed Attempt 1 - executeMethod

I attempted to pass in command line parameters using a static Build method in the Assets/Editor folder.

namespace Lang.Clomper.EditorExtensions
{
    public static class Build
    {
        public static void SetBundleVersionNumber()
        {
            string[] args = System.Environment.GetCommandLineArgs();

            for (var i = 0; i < args.Length; i++)
            {
                var arg = args[i];
                if (arg.Contains("build"))
                {
                    UnityEditor.PlayerSettings.bundleVersion = args[i + 1];
                }
            }

        }
    }
}

The powershell command line is:

Start-Process -FilePath $unityExe -ArgumentList "-batchmode", "-quit", "-projectPath", $projectPath, "-buildWindows64Player", "$outputPath\Clomper.exe", "-logFile", $logFile, "build", $versionNumber -Wait

The code fails on UnityEditor.PlayerSettings.bundleVersion the log reads:

Assets\Editor\Build.cs(16,21): error CS0234: The type or namespace name 'PlayerSettings' does not exist in the namespace 'UnityEditor' (are you missing an assembly reference?)

Failed Attempt 2 - IPreprocessBuildWithReport

Also located in Assets/Editor. This takes the command line arguments, finds “build” and sets bundle version to the argument that follows.

using UnityEditor.Build;
using UnityEditor.Build.Reporting;
using UnityEngine;

namespace Lang.Clomper
{
    public class BuildPreprocessor : IPreprocessBuildWithReport
    {
        public int callbackOrder => 0;

        public void OnPreprocessBuild(BuildReport report)
        {
            string[] args = System.Environment.GetCommandLineArgs();

            for (var i = 0; i < args.Length; i++)
            {
                var arg = args[i];
                if (arg.Contains("build"))
                {
                    Debug.Log($"Setting build version to {args[i + 1]}");
                    UnityEditor.PlayerSettings.bundleVersion = args[i + 1];
                }
            }
        }
    }
}

The powershell command to build this (similar to above without -executeMethod):

Start-Process -FilePath $unityExe -ArgumentList "-batchmode", "-quit", "-projectPath", "$projectPath", "-buildWindows64Player", "$outputPath\Clomper.exe", "-logFile", "$logFile", "build", "$versionNumber" -Wait

The code fails on UnityEditor.PlayerSettings.bundleVersion the error is:

Assets\Editor\BuildPreprocessor.cs(1,19): error CS0234: The type or namespace name 'Build' does not exist in the namespace 'UnityEditor' (are you missing an assembly reference?)

Custom asmdef info

I suspected this was the problem, I had a single custom asmdef in the root folder.

  • Lang.Clomper found in the root folder, targeting Win64 only with the majority of my project/asset references.

Solution

You need a custom asmdef in the Editor folder that only targets the Editor and references any assemblies you use in your code.

  • Lang.Clomper.Editor found in Assets/Editor targeting only the Editor platform.
  • It references Lang.Clomper and Netcode for GameObjects. These are the only libraries that get used by my Editor scripts. If you are just setting version number, you won’t need any other references.

Be really careful with the checkboxes when you untick “Target All” because the list below becomes and include rather than exclude. I think that’s what I missed at first.

I hope that helps others!

1 Like