Unity Windows 叠加

Unity Windows Overlay

我正在尝试使用 Unity 为 Windows OS 制作一个叠加层。 我从 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);
        }
    }

现在问题是:透明度(与着色器和 material 一起工作)、点击率和 alwaysOnTop 属性正在工作 perfectly.But,如果我点击 window,应用程序将暂停。我如何实现程序在不专注时不暂停?

另一件事是,如果您启动它,整个程序就可以正常工作 windowed,但不能全屏显示。如果我以全屏模式启动,当我单击某些内容时它会最小化。

谢谢!

他们可能都有关系。 Unity 有一个选项 Application.runInBackground

Should the player be running when the application is in the background?

Default is false (application pauses when it is in the background).

您可以在您的脚本中启用它,例如

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

或在播放器设置中 编辑项目设置玩家决议和陈述

在后台启用运行

选项 在后台可见 可能对您也很有趣

Enable this option to show the application in the background if Windowed Fullscreen Mode is used (in Windows).

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


一般提示:

您应该用

包装整个 Start 方法
#if !UNITY_EDITOR
    private void Start()
    {

    }
#endif

如果你不这样做也不错,但 Unity 也会调用一个空的 Start 方法,造成不必要的开销。