Unity command line -- how to acces existing instance without -quit(ing) for every command

I'm successfully able to run basic Unity Editor functions from the command line, with a command like this:

"C:\Program Files\Unity\Hub\Editor\2019.1.0b1\Editor\Unity"  -batchmode -quit -projectPath "C:\Users\me\OneDrive\Documents\totally empty" -executeMethod COBY.BuildIt -logfile "C:\Users\me\OneDrive\Desktop\wow.txt"

and some C# code like this:

public class COBY : MonoBehaviour
{
    public static void BuildIt() {
        AssetBundleBuild[] assets = new AssetBundleBuild[2];

        assets[0].assetBundleName = "cobysNewBundle";
        string[] assetNames = new string[2];
        assetNames[0] = "Assets/CobyThings/teffilin.fbx";
        assetNames[1] = "Assets/CobyThings/up.fbx";
        assets[0].assetNames = assetNames;

        assets[1].assetBundleName = "anotherBundle";
        string[] notherBundleNames = new string[1];
        notherBundleNames[0] = "Assets/CobyThings/atzmusPic.png";
        assets[1].assetNames = notherBundleNames;

        var path = "Assets/m23214ycobytest.txt";
        StreamWriter writer = new StreamWriter(path, true);
        writer.WriteLine("Just wrote to these assets!");
        writer.Close();
        Debug.Log("ASDFGG");
        MonoBehaviour.print("wow");

        BuildPipeline.BuildAssetBundles("Assets/CobysAssets", assets, BuildAssetBundleOptions.None, BuildTarget.WebGL);
    }
}

which is actually working great so far (as long as I put the C# file in the "Assets/Editor" folder), both when I run it as a MenuItem in the Unity Editor and even when I call the command from the command line.

The problem:

I would like to be able to call multiple commands from the Unity Editor (after checking that the log file has completed one command, for example). Currently, to do this, I need to add the -quit argument for each command line call, which quits the entire unity instance, and then when I want to run a new command, it has to start up unity all over again, which could take a lot of time if I was running many commands.

How can I simply access the already-running unity instance that's either running in batchmode, or even if its open in the editor? Meaning, when I take out the -quit parameter, then the command still works, but it's clear that Unity is still running (as I can see from the Task Manager and also when I try to run the command again I get an error in the log that Unity is already running the current project), and obviously when the actual Unity Editor is running with the project open, then the log gives the error that another Unity instance is running with this project etc...

So is there a way to simply get the current Unity instance that's running with the desired project, and just run a command from that, or do I have to restart Unity every time I want to run a command from the command line?

Upvotes: 0

Views: 2544

Answers (1)

derHugo
derHugo

Reputation: 90789

Maybe not exactly what you are after - afaik it is not possible to send commandline arguments to an already running process - but you could use one central -executeMethod call together with System.Environment.GetCommandLineArgs(); to get some custom parameters in order to tell that central method what to do ... something like

public class COBY : MonoBehaviour
{
    public static void ExecuteFromExternal() 
    {
        string[] args = System.Environment.GetCommandLineArgs ();

        // maybe also add a flag to make sure a second thing is only done
        // if the one before was successfull
        bool lastSucceeded = true;
        // just in combination with the flag to know which was the last
        // command executed
        int lastI = 0;

        for (int i = 0; i < args.Length; i++) 
        {
            Debug.Log ("ARG " + i + ": " + args [i]);

            // interrupt if one command failed
            if(!lastSucceeded)
            {
                Debug.LogFormat("Last command \"{0}\" failed! -> cancel", args[lastI]);
                return;
            }

            switch(args[i])
            {
                case "-doSomething":
                    lastI = i;

                    // do something
                    lastSucceeded = wasItSuccessfull;
                    break;

                case "-build":
                    lastI = i;

                    // maybe you want to get some values after "-build"
                    // because they are needed let's say e.g. an int and a path
                    int value = args[i + 1];
                    string path = args[i + 2];
                    // maybe a sanity check here

                    // now build using that value and the path

                    // you could increase i since the next two
                    // arguments don't have to be checked
                    i += 2;
                    break;
            }
        }
    }
}

So you could now call e.g.

"C:\...\Unity" -batchmode -quit -projectPath "C:\..." -executeMethod COBY.ExecuteFromExternal -doSomething -logfile "C:\...\wow.txt"

to only eecute the first method or e.g.

"C:\...\Unity" -batchmode -quit -projectPath "C:\..." -executeMethod COBY.ExecuteFromExternal -build 42 "C:\some\path" -logfile "C:\...\wow.txt"

to only execute the build part or e.g.

"C:\...\Unity" -batchmode -quit -projectPath "C:\..." -executeMethod COBY.ExecuteFromExternal -doSomething -build 42 "C:\some\path" -logfile "C:\...\wow.txt"

to execute both (in that order).


As long as you are not doing any async stuff there you should be fine and the second method should not be executed before the first one finished. Using the flag lastSucceeded you can also controll whether a second thing should be done anyway if the one before failed or not.

Upvotes: 1

Related Questions