Unity 2018+(含2020)编辑器实现GameView全屏的方法及反射报错排查
Unity 2018+ 编辑器Game窗口全屏的适配方案
旧脚本报错的核心原因
- 你在
System.Object Res = GetMainGameView.Invoke (null, null);行触发的异常,本质不是Unity彻底禁用了对GetMainGameView的反射访问,而是2018及以上版本中该方法的绑定规则发生了变化:- 旧脚本仅匹配
NonPublic | Static的方法绑定位,而部分新版Unity版本中GetMainGameView的访问修饰符被调整为公开,对应绑定参数完全无法匹配,最终反射拿到的GetMainGameView对象为null,调用空对象自然会抛出异常。 - 旧脚本中进入编辑模式时直接
gameView.Close()的逻辑,也不符合新版编辑器的窗口生命周期规则,容易触发编辑器崩溃、用户自定义布局被意外破坏。
- 旧脚本仅匹配
跨版本兼容的可靠实现逻辑
- 调整反射的绑定参数,增加兜底查找逻辑,避免反射匹配失败直接崩溃:
System.Type gameViewType = System.Type.GetType("UnityEditor.GameView,UnityEditor"); // 多绑定位匹配,兼容不同版本的方法可见性调整 System.Reflection.MethodInfo getMainGameViewMethod = gameViewType.GetMethod( "GetMainGameView", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public ); EditorWindow gameView = null; // 反射拿不到目标方法时的兜底逻辑:遍历已打开的编辑器窗口匹配GameView类型 if (getMainGameViewMethod != null) { gameView = (EditorWindow)getMainGameViewMethod.Invoke(null, null); } else { EditorWindow[] allWindows = Resources.FindObjectsOfTypeAll<EditorWindow>(); foreach (var win in allWindows) { if (win.GetType() == gameViewType) { gameView = win; break; } } } - 用GameView内置的全屏属性替代手动修改窗口位置、大小的逻辑,稳定性远高于旧的手动计算方式:
switch (_playModeStateChange) { case PlayModeStateChange.EnteredPlayMode: // 确保GameView窗口激活显示 gameView.Show(); gameView.Focus(); // 通过反射设置内置全屏属性,实现无工具栏遮挡的真全屏 var fullScreenProp = gameViewType.GetProperty("fullScreen", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); fullScreenProp.SetValue(gameView, true, null); break; case PlayModeStateChange.EnteredEditMode: // 退出播放时仅恢复窗口状态,不要直接关闭窗口破坏用户布局 var exitFullScreenProp = gameViewType.GetProperty("fullScreen", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); exitFullScreenProp.SetValue(gameView, false, null); break; } - 原脚本的菜单开关逻辑、PlayerPrefs存储状态的部分可以完全保留,不需要额外修改,仅替换上述反射调用、窗口控制的代码段即可。
实现注意事项
- 不要手动将GameView的
minSize、maxSize强制设为屏幕分辨率:在多显示器、系统显示缩放比例不为100%的场景下,固定尺寸会导致窗口错位、无法正常退出全屏。 - 不要在进入编辑模式时直接调用
gameView.Close():该操作会把用户原本停靠在编辑器布局里的GameView标签页彻底关闭,破坏自定义工作区布局,仅将全屏属性重置为false即可恢复窗口原始状态。
内容的提问来源于stack exchange,提问作者Richard
相关产品推荐
相关产品推荐

