2
\$\begingroup\$

I'm looking for a way to auto switch the Unity layout when I go to play mode.

I want to Unity Editor layout automatically changes to my preset layout when I click on Play button and When I stop the game, It goes back to the default layout.

\$\endgroup\$
5
\$\begingroup\$

After reading Unity API, I found the solution! It's absolutely possible to change the Unity layout during the Play Mode. We can use Unity Utility class in UnityEditor namespace.

The code below will be run in Editor and change the layout if we click on play button.

Update: Amended code, Thanks to @Ed Marty


using UnityEngine;
using UnityEditor;

namespace Assets.Editor {
    [InitializeOnLoad]
    public class AutoLayoutChanger {
        static AutoLayoutChanger() {
            EditorApplication.playmodeStateChanged = HandleOnPlayModeChanged;
        }

        static void HandleOnPlayModeChanged() {
            // This method is run whenever the playmode state is changed.
            if (EditorApplication.isPlaying) {
                EditorUtility.LoadWindowLayout("Preset Layout");
                // do stuff when the editor is played.
            } else if (!EditorApplication.isPaused) {
                EditorUtility.LoadWindowLayout("Default Layout");
                // other than playmode
            }
        }
    }
}
\$\endgroup\$
  • 3
    \$\begingroup\$ This might make more sense as an editor-only script, rather than one that extends MonoBehaviour. Get rid of : MonoBehaviour, replace [ExecuteInEditMode] with [InitializeOnLoad], change void Awake() to static AutoLayoutChange(), and add static before void HandleOnPlayModeChanged(). Make sure to put it in an Editor folder, too. \$\endgroup\$ – Ed Marty Nov 8 '17 at 15:17
1
\$\begingroup\$

So going around the interwebs I came up with this solution.

You can save your custom layout by clicking the layout button in the top right of the editor and the selecting save layout.

Now we need a [ExecuteInEditMode] scripted place inside the scene we want to change layout when entering playmode.

using UnityEditor;
using UnityEngine;
[ExecuteInEditMode]
public class ChangeLayoutInPlayMode : MonoBehaviour  {
    void OnEnable()
    {
#if UNITY_EDITOR
        EditorApplication.playModeStateChanged += StateChange;
#endif
    }
#if UNITY_EDITOR
    void StateChange(PlayModeStateChange state)
    {
        if (EditorApplication.isPlayingOrWillChangePlaymode && EditorApplication.isPlaying)
        {
            LayoutTool.LoadLayoutFromAsset("C:/Users/Uri/AppData/Roaming/Unity/Editor-5.x/Preferences/Layouts/custom.wlt");
        }
        if ( !EditorApplication.isPlaying)
        {
            LayoutTool.LoadLayoutFromAsset("C:/Users/Uri/AppData/Roaming/Unity/Editor-5.x/Preferences/Layouts/Default.wlt");
        }
    }
#endif

Note that you would have to change the path to the default layout and the custom one to fit your instalation of unity. It is generally in User/usernama etc.

Finaly the thing that does the magic of saving the custom layout and loading it is this utility class ( not mine got it from the web)

using UnityEngine;
using UnityEditor;

using System.IO;
using System.Reflection;

using Type = System.Type;

public static class LayoutTool
{

    private static MethodInfo _miLoadWindowLayout;
    private static MethodInfo _miSaveWindowLayout;
    private static MethodInfo _miReloadWindowLayoutMenu;

    private static bool _available;
    private static string _layoutsPath;

    static LayoutTool()
    {
        Type tyWindowLayout = Type.GetType("UnityEditor.WindowLayout,UnityEditor");
        Type tyEditorUtility = Type.GetType("UnityEditor.EditorUtility,UnityEditor");
        Type tyInternalEditorUtility = Type.GetType("UnityEditorInternal.InternalEditorUtility,UnityEditor");

        if (tyWindowLayout != null && tyEditorUtility != null && tyInternalEditorUtility != null)
        {
            MethodInfo miGetLayoutsPath = tyWindowLayout.GetMethod("GetLayoutsPath", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static);
            _miLoadWindowLayout = tyWindowLayout.GetMethod("LoadWindowLayout", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(string), typeof(bool)  }, null);
            _miSaveWindowLayout = tyWindowLayout.GetMethod("SaveWindowLayout", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(string) }, null);
            _miReloadWindowLayoutMenu = tyInternalEditorUtility.GetMethod("ReloadWindowLayoutMenu", BindingFlags.Public | BindingFlags.Static);

            if (miGetLayoutsPath == null || _miLoadWindowLayout == null || _miSaveWindowLayout == null || _miReloadWindowLayoutMenu == null)
                return;

            _layoutsPath = (string)miGetLayoutsPath.Invoke(null, null);
            if (string.IsNullOrEmpty(_layoutsPath))
                return;

            _available = true;
        }
    }

    // Gets a value indicating whether all required Unity API
    // functionality is available for usage.
    public static bool IsAvailable
    {
        get { return _available; }
    }

    // Gets absolute path of layouts directory.
    // Returns `null` when not available.
    public static string LayoutsPath
    {
        get { return _layoutsPath; }
    }

    // Save current window layout to asset file.
    // `assetPath` must be relative to project directory.
    public static void SaveLayoutToAsset(string assetPath)
    {
        SaveLayout(Path.Combine(Directory.GetCurrentDirectory(), assetPath));
    }

    // Load window layout from asset file.
    // `assetPath` must be relative to project directory.
    public static void LoadLayoutFromAsset(string assetPath)
    {
        if (_miLoadWindowLayout != null)
        {
            string path = Path.Combine(Directory.GetCurrentDirectory(), assetPath);
            _miLoadWindowLayout.Invoke(null, new object[] { path,true });
        }
    }

    // Save current window layout to file.
    // `path` must be absolute.
    public static void SaveLayout(string path)
    {
        if (_miSaveWindowLayout != null)
            _miSaveWindowLayout.Invoke(null, new object[] { path });
    }

}
\$\endgroup\$
0
\$\begingroup\$

Unchecking Maximize on Play might be helpful. Additionally, pressing pause button changes the layout while playing.

\$\endgroup\$
  • 1
    \$\begingroup\$ I think OP is asking about a way to switch to a specific preset layout that's not the maximized or editing layout they're currently using, and to be able to use this layout while the game is running, not paused. \$\endgroup\$ – DMGregory Nov 8 '17 at 12:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.