Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Display Psychtoolbox-like full-screen game view window on the second monitor in the Unity Editor

Discussion in 'Scripting' started by Jialiang_Lu, Jul 22, 2020.

  1. Jialiang_Lu

    Jialiang_Lu

    Joined:
    Dec 9, 2018
    Posts:
    2
    I'm a neuroscientist and I was planning to use the Unity Editor as my platform for displaying the game to the subject and control the flow of the experiment in the Editor. However I've been struggling a lot on how to make my second monitor (the subject monitor) display the game view full-screen during Play mode. Inspired by this link: https://www.reddit.com/r/Unity3D/comments/2lymim/full_full_screen_on_play_script_freebie_for/ I finally managed to get a nice full-screen game view on the second monitor without anything else. Apart from phychophysical experiments, this should be useful for anyone developing VR as well. Here's the code:

    Code (CSharp):
    1. using System;
    2. using System.Diagnostics;
    3. using System.Reflection;
    4. using UnityEngine;
    5. using UnityEditor;
    6. using Debug = UnityEngine.Debug;
    7.  
    8. namespace Test
    9. {
    10.     public enum MonitorMode
    11.     {
    12.         Internal,
    13.         External,
    14.         Clone,
    15.         Expand,
    16.     }
    17.  
    18.     public class MonitorDisplay : MonoBehaviour
    19.     {
    20.         public const float TabHeight = 22f;
    21.  
    22.         private Process _displaySwitch;
    23.         private readonly Assembly _assembly = typeof(EditorWindow).Assembly;
    24.         private Type _gameViewType;
    25.         private EditorWindow _subjectGameWindow;
    26.         private Rect _subjectGamePos;
    27.  
    28.         private void Awake()
    29.         {
    30.             _displaySwitch = new Process
    31.             {
    32.                 StartInfo =
    33.                 {
    34.                     WindowStyle = ProcessWindowStyle.Hidden,
    35.                     CreateNoWindow = true,
    36.                     UseShellExecute = false,
    37.                     FileName = @"C:\Windows\System32\DisplaySwitch.exe"
    38.                 },
    39.                 EnableRaisingEvents = true
    40.             };
    41.  
    42.             _gameViewType = _assembly.GetType("UnityEditor.GameView");
    43.  
    44.             _subjectGamePos = new Rect(Screen.currentResolution.width, 0f - TabHeight, Screen.currentResolution.width,
    45.                 Screen.currentResolution.height + TabHeight);
    46.             Debug.Log(_subjectGamePos);
    47.         }
    48.  
    49.         private void Start()
    50.         {
    51.             SwitchMonitorMode(MonitorMode.Expand);
    52.  
    53.             _subjectGameWindow = (EditorWindow)ScriptableObject.CreateInstance(_gameViewType);
    54.             _subjectGameWindow.titleContent = new GUIContent("Subject Game View");
    55.             _subjectGameWindow.ShowPopup();
    56.             _subjectGameWindow.minSize = new Vector2(Screen.currentResolution.width,
    57.                 Screen.currentResolution.height + TabHeight);
    58.             _subjectGameWindow.maxSize = _subjectGameWindow.minSize;
    59.             _subjectGameWindow.position = _subjectGamePos;
    60.         }
    61.  
    62.         private void OnDestroy()
    63.         {
    64.             SwitchMonitorMode(MonitorMode.Clone);
    65.             _subjectGameWindow.Close();
    66.         }
    67.  
    68.         private void SwitchMonitorMode(MonitorMode mode)
    69.         {
    70.             switch (mode)
    71.             {
    72.                 case MonitorMode.Internal:
    73.                     _displaySwitch.StartInfo.Arguments = @"/internal";
    74.                     break;
    75.                 case MonitorMode.External:
    76.                     _displaySwitch.StartInfo.Arguments = @"/external";
    77.                     break;
    78.                 case MonitorMode.Clone:
    79.                     _displaySwitch.StartInfo.Arguments = @"/clone";
    80.                     break;
    81.                 case MonitorMode.Expand:
    82.                     _displaySwitch.StartInfo.Arguments = @"/extend";
    83.                     break;
    84.                 default:
    85.                     throw new ArgumentOutOfRangeException(nameof(mode), mode, "Unknown monitor mode");
    86.             }
    87.             _displaySwitch.Start();
    88.             _displaySwitch.WaitForExit();
    89.             if (_displaySwitch.ExitCode != 0)
    90.                 Debug.LogError("Windows DisplaySwitch.exe exited with error!");
    91.         }
    92.     }
    93. }
    The key is to use ShowPopup() instead of Show(). I also included the function of automatically switching the display mode between duplicate and expand, because the display has to be duplicate mode when I'm not using Unity. If you want to change any properties of this second game view window, you'll have to read the source code https://github.com/Unity-Technologies/UnityCsReference/blob/master/Editor/Mono/GameView/GameView.cs and use reflection, I believe.

    I hope it's useful for someone.
     
    Last edited: Jul 22, 2020
    Kurt-Dekker likes this.