Search Unity

Load Specific Scene from Command Line?

Discussion in 'Editor & General Support' started by NovaDynamics, Mar 18, 2021.

  1. NovaDynamics

    NovaDynamics

    Joined:
    Sep 6, 2017
    Posts:
    25
    Hey guys.
    I need to be able to build a Unity project that has multiple scenes (say: Scene1, Scene2, Scene3), then be able to start the application with a command line argument that loads a specific scene. eg.
    Code (CMD):
    1. C:/ProjectName/UnityProject.exe Scene1
    I am aware that I could do this by creating a main scene with a loader script on it, then have it parse the command line and load the parsed scene, but the catch here is that I need the application to load as quickly as possible when I start it. I am wondering if this is the only approach to this problem, or if there is a more efficient way to do this.

    The reason I need this (for those wondering) is for constructing virtual unit tests for a robot we are working on. As you can imagine I need these test environments to spawn quickly.
    Thanks!
     
  2. mgear

    mgear

    Joined:
    Aug 3, 2010
    Posts:
    9,411
    random ideas:
    i'd think that parsing it there wouldn't make any measurable difference..
    or if you can have all scenes already in the main scene, but disabled,
    then can just activate them. (but might increase initial loading, if they are heavy scenes..)
     
  3. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    If your starting scene is kept clean of asset references, I'd expect it to load and then start loading the scene you specify in the command line very quickly. I'm not aware of a way to otherwise get a build to launch with a scene other than the first scene.
     
  4. NovaDynamics

    NovaDynamics

    Joined:
    Sep 6, 2017
    Posts:
    25
    OK, thanks for the info. It does indeed seem to load fast as long as I keep my starting scene clean of everything but the scene loader script:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.SceneManagement;
    5.  
    6. public class SceneLoader : MonoBehaviour
    7. {
    8.     private void Awake()
    9.     {
    10.         string[] args = System.Environment.GetCommandLineArgs();
    11.  
    12.         if (args.Length < 2) Application.Quit();
    13.  
    14.         string scene = args[1];
    15.  
    16.         SceneManager.LoadScene(scene, LoadSceneMode.Single);
    17.  
    18.     }
    19.  
    20. }
     
    DavidLGoldberg and Joe-Censored like this.
  5. dan_ginovker

    dan_ginovker

    Joined:
    Jun 13, 2021
    Posts:
    76
    In case anyone finds this thread from Google and wants to run the game to test things headlessly (like me), here's all the info you'll need:


    public class PlayTestsLoader : MonoBehaviour
    {
    public static bool PlayTestsRunning = false;
    public static bool PlayTestsWantToStop = false;
    // Run with (note paths are Linux syntax - replace as needed)
    // ./Unity -projectPath ~/unityprojectname -executeMethod PlayTestsLoader.LoadTestScenes -logfile "~unityprojectname/logs.txt" -batchmode
    public static void LoadTestScenes()
    {
    try
    {
    EditorUserBuildSettings.SwitchActiveBuildTarget(BuildTargetGroup.Android, BuildTarget.Android); // Test Android code paths as if you were doing it manually in Editor
    EditorSceneManager.OpenScene($"Assets/Scenes/mainscene.unity"); // Load the scene in Editor - Not at play time!
    EditorApplication.isPlaying = true; // When this static method returns, setting isPlaying to true will start the game
    TestLog($"Entered playmode");
    }
    catch (Exception e)
    {
    TestLog($"Had exception {e}");
    }
    TestLog($"Complete PlayTestsLoader.LoadTestScenes");
    }

    static void TestLog(string log)
    {
    Debug.Log($"=== PlayTests === {log}");
    }

    public void Update()
    {
    if (PlayTestsRunning && PlayTestsWantToStop)
    {
    TestLog("ALL TESTS COMPLETED -- RETURNING 0");
    EditorApplication.Exit(0); // This will stop the game from running when you're done, and make the headless (invisible) editor exit
    }
    }

    public void OnEnable()
    {
    PlayTestsRunning = true;
    TestLog("PlayTestsLoader Monobehaviour started");
    StartCoroutine(PlayTestJourneyController());
    }

    IEnumerator PlayTestJourneyController()
    {
    yield return StartPvP();
    yield return SayHelloAfterPvP();

    PlayTestsWantToStop = true;
    yield return null;
    }

    IEnumerator StartPvP()
    {
    TestLog($"Hello from StartPvP");
    yield break;
    }

    IEnumerator SayHelloAfterPvP()
    {
    TestLog($"Hello from SayHelloAfterPvP");
    yield break;
    }
    }