【问题标题】:Unity Windows OverlayUnity Windows 覆盖
【发布时间】:2019-10-26 02:04:09
【问题描述】:

我正在尝试使用 Unity 为 Windows 操作系统制作叠加层。 我从UnityForum 的这个线程中获得了所需的所有信息。 我使用的脚本如下:

    using System;
    using System.Runtime.InteropServices;
    using UnityEngine;
    
    public class TransparentWindow : MonoBehaviour
    {
        [SerializeField]
        private Material m_Material;
        
        private struct MARGINS
        {
            public int cxLeftWidth;
            public int cxRightWidth;
            public int cyTopHeight;
            public int cyBottomHeight;
        }
        
        [DllImport("user32.dll")]
        private static extern IntPtr GetActiveWindow();
        
        [DllImport("user32.dll")]
        private static extern int SetWindowLong(IntPtr hWnd, int nIndex, uint dwNewLong);
        
        [DllImport("user32.dll")]
        static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
        
        [DllImport("user32.dll", EntryPoint = "SetLayeredWindowAttributes")]
        static extern int SetLayeredWindowAttributes(IntPtr hwnd, int crKey, byte bAlpha, int dwFlags);
        
        [DllImport("user32.dll", EntryPoint = "SetWindowPos")]
        private static extern int SetWindowPos(IntPtr hwnd, int hwndInsertAfter, int x, int y, int cx, int cy, int uFlags);
        
        [DllImport("Dwmapi.dll")]
        private static extern uint DwmExtendFrameIntoClientArea(IntPtr hWnd, ref MARGINS margins);
        
        const int GWL_STYLE = -16;
        const uint WS_POPUP = 0x80000000;
        const uint WS_VISIBLE = 0x10000000;
        const int HWND_TOPMOST = -1;
        
        void Start()
        {
#if !UNITY_EDITOR // You really don't want to enable this in the editor..
            int fWidth = Screen.width;
            int fHeight = Screen.height;
            var margins = new MARGINS() { cxLeftWidth = -1 };
            var hwnd = GetActiveWindow();
        
            SetWindowLong(hwnd, GWL_STYLE, WS_POPUP | WS_VISIBLE);
        
            // Transparent windows with click through
            //GWL_EXSTYLE=-20; WS_EX_LAYERED=524288=&h80000, WS_EX_TRANSPARENT=32=0x00000020L
            SetWindowLong(hwnd, -20, 524288 | 32);
            // Transparency=51=20%, LWA_ALPHA=2
            SetLayeredWindowAttributes(hwnd, 0, 255, 2);
            //SWP_FRAMECHANGED = 0x0020 (32); //SWP_SHOWWINDOW = 0x0040 (64)
            SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, fWidth, fHeight, 32 | 64); 
            DwmExtendFrameIntoClientArea(hwnd, ref margins);
#endif
        }
        
        void OnRenderImage(RenderTexture from, RenderTexture to)
        {
            Graphics.Blit(from, to, m_Material);
        }
    }

现在的问题是:透明度(适用于着色器和材质)、Click-through 和 alwaysOnTop 属性工作正常。但是,如果我单击窗口,应用程序将暂停.如何实现程序在不集中时不暂停?

另一件事是,如果您以窗口方式启动它,但不能以全屏方式启动,整个程序就可以正常工作。如果我从全屏开始,当我点击某些东西时,它会最小化。

谢谢!

【问题讨论】:

    标签: c# .net unity3d winapi user32


    【解决方案1】:

    它们可能都相关。 Unity有一个选项Application.runInBackground

    播放器是否应该在应用程序在后台运行时运行?

    默认为false(应用程序在后台暂停)。

    你可以在你的脚本中启用它

    private void Awake()
    {
        Application.runInBackground = true;
    }
    

    或在播放器设置中编辑 → 项目设置 → 播放器 → 解决方案和演示文稿

    启用 在后台运行

    Visible in Background 选项可能对您来说也很有趣

    如果使用窗口全屏模式(在 Windows 中),启用此选项以在后台显示应用程序。

    另请参阅Standalone Player settings 了解更多信息。


    一般提示:

    你应该用

    包裹整个Start方法
    #if !UNITY_EDITOR
        private void Start()
        {
    
        }
    #endif
    

    如果你不这样做还不错,但 Unity 会调用一个空的 Start 方法,从而导致不必要的开销。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-01-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-25
      • 1970-01-01
      • 1970-01-01
      • 2016-10-29
      相关资源
      最近更新 更多