有办法将Unity3d带到前台吗?

6

我使用了 Application.OpenURL 将我的用户发送到浏览器中,现在我想以编程方式将 Unity 程序切换回前台。

有没有无需插件就能实现的方法?

谢谢。


我使用 https://dev59.com/HGMm5IYBdhLWcg3wFL_s#18052274。 - xmedeko
你使用哪个平台?实际上,有一种花哨的方式可以做到,但需要使用与平台相关的Webview。 - Brian Choi
你要把用户发送到哪里?这是你自己的网页,你可以控制在该页面上执行的代码吗?还是一个通用页面? - Remy
@BrianChoi 我不知道peterept,但我正在使用Windows 10。 - glenneroo
4个回答

3

在将用户发送到其他窗口之前,使用 GetActiveWindow 获取窗口句柄,然后使用该句柄调用 SetForegroundWindow。在调用 SetForegroundWindow 之前,您可以尝试模拟按下 Alt 键来打开菜单,以遵守 SetForegroundWindow 的某些限制。

private IntPtr unityWindow;

[DllImport("user32.dll")] 
static extern IntPtr GetActiveWindow();

[DllImport("user32.dll")] 
static extern bool SetForegroundWindow(IntPtr hWnd); 

[DllImport("user32.dll")]
static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, int dwExtraInfo);

const int ALT = 0xA4;
const int EXTENDEDKEY = 0x1;
const int KEYUP = 0x2;

private void SendUser() 
{
    unityWindow = GetActiveWindow();

    Application.OpenURL("http://example.com");

    StartCoroutine(RefocusWindow(30f));
}


private IEnumerator RefocusWindow(float waitSeconds) {
    // wait for new window to appear
    yield return new WaitWhile(() => unityWindow == GetActiveWindow());

    yield return new WaitForSeconds(waitSeconds);

    // Simulate alt press
    keybd_event((byte)ALT, 0x45, EXTENDEDKEY | 0, 0);

    // Simulate alt release
    keybd_event((byte)ALT, 0x45, EXTENDEDKEY | KEYUP, 0);

    SetForegroundWindow(unityWindow);
}

我修复了IntPtr编译器错误,但在Windows 10中仍似乎不起作用。它在任务栏中闪烁,但窗口实际上并没有获得焦点。 - glenneroo
1
@glenneroo SetForegroundWindow 函数将窗口置于前台或仅在任务栏中闪烁其条的操作存在一些限制。似乎您可以尝试发送 alt 键以打开菜单,这将允许另一个窗口(在此情况下为 Unity)控制前景。我编辑了我的答案以提供更多信息。 - Ruzihm
1
这个解决方案在 Windows 10 上非常好用,适用于 Windows_x64 桌面构建。 - Clay Fowler
@ClayFowler 谢谢您的反馈 :) - Ruzihm

0

这对我在Unity 5.0.1 / Windows 8.1上有效:

using UnityEngine;
using System;
using System.Collections;
using System.Runtime.InteropServices;

public class ForeGrounder : MonoBehaviour {

    private const uint LOCK = 1;
    private const uint UNLOCK = 2;

    private IntPtr window;

    void Start() {
        LockSetForegroundWindow(LOCK);
        window = GetActiveWindow();
        StartCoroutine(Checker());
    }

    IEnumerator Checker() {
        while (true) {

            yield return new WaitForSeconds(1);
            IntPtr newWindow = GetActiveWindow();

            if (window != newWindow) {
                Debug.Log("Set to foreground");
                SwitchToThisWindow(window, true);
            }
        }
    }

    [DllImport("user32.dll")]
    static extern IntPtr GetActiveWindow();
    [DllImport("user32.dll")]
    static extern bool LockSetForegroundWindow(uint uLockCode);
    [DllImport("user32.dll")]
    static extern void SwitchToThisWindow(IntPtr hWnd, bool fAltTab);
}

SwitchToThisWindow - 此函数不适用于一般用途。在后续的Windows版本中,它可能会被更改或不可用。 - xmedeko
问题出在 window = GetActiveWindow(); 当用户在此代码运行之前切换到另一个应用程序,即在应用程序初始化之前。那么结果就是 0 - xmedeko

0

对于 Mac 独立应用程序,我们可以尝试

public void OpenURLInDefaultBrowser(string URL)
    {

#如果是Mac操作系统

Screen.fullScreenMode = FullScreenMode.Windowed;

#endif Application.OpenURL(URL);

        StartCoroutine(ReFocusUnity());
    }

    private IEnumerator ReFocusUnity()
    {
        //You can wait for some seconds or wait for any callback you are expecting
        yield return new WaitForSeconds(5f);

#if UNITY_STANDALONE_OSX

        Screen.fullScreenMode = FullScreenMode.FullScreenWindow;

#endif }


0
如果您正在Windows中使用Unity3D,请在调用Application.OpenURL(...)后尝试以下代码:
[DllImport("user32.dll")]
private static extern bool SetForegroundWindow(IntPtr hWnd);

var prc = Process.GetProcessesByName("..."); //Get Unity's process, or 
var prc = Process.GetCurrentProcess();
if (prc.Length > 0) 
    SetForegroundWindow(prc[0].MainWindowHandle);

2
目前还没有成功。上面的代码总是返回窗口句柄为0。我改成了EnumWindows,确实得到了一个有效的窗口句柄。但调用SetForegroundWindow()没有任何效果。我会继续挖掘。 - peterept

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接