2

我正在开发一个具有以下属性的项目:

  1. jQuery 驱动页面
  2. unityobject.js使用 jQuery 和(根据 Unity 的指令)嵌入到页面的 Unity 3d 播放器
  3. 当用户的光标在 Unity 的画布区域内时,Unity 具有自定义鼠标光标

问题: Unity 捕获鼠标光标,但在包含它的网页变为非活动状态时不会释放它。这意味着如果用户切换到不同的选项卡(或打开一个新窗口),当用户将鼠标悬停在 Unity 所在的区域上时,鼠标光标就会消失。这是 Unity 3d 论坛中描述的统一错误:http: //forum.unity3d.com/threads/4565-Unity-Web-player-issue-mouse-hidden-for-all-new-windows

不,它仍然没有在最新版本的 Unity Web 客户端中修复。

为了缓解这个问题,我们决定让 Unity 通过 Javascript 监听当前浏览器窗口的状态,并根据接收到的状态捕获/释放自定义鼠标光标。但还有其他问题:

Unity 如何接收窗口状态:

// GetUnity returns the Unity object in the DOM<br>
NAMESPACE.windowStatus = function( statusStr ) {
    GetUnity().SendMessage( "_AppShell", "OnRecieveWindowStatusFromWebPage", statusStr );
}

我试过以下方法...

方法一:将事件绑定到“window”对象

$( window ).live( 'focus', function() {
    NAMESPACE.windowStatus( 'active' );
} );

$( window ).live( 'blur', function() {
    NAMESPACE.windowStatus( 'inactive' );
} );

问题:在 IE7 和 IE8 中,新的浏览器选项卡不会被视为不同的“窗口”,因此代码对 Unity 没有影响。它仅在打开真正单独的浏览器窗口时才有效。


方法2:将事件绑定到“文档”对象
像这样:$( document ).live(...);

问题: $( document )在 jQuery 中实际上什么也没做。发现了艰难的方式。
来源:http: //forum.jquery.com/topic/should-document-live-map-to-document-bind-window-too


方法3:将事件绑定到<body>对象
像这样:$( 'body' ).live(...);

问题:不知何故,IE 无法识别 Unity 对象是 DOM 的一部分(尽管使用了该.live()方法)。因此,每次用户单击嵌入式 Unity 播放器时,浏览器都会blur向 Unity 发送一个事件,并且鼠标光标会被锁定(单击 Unity 时会console.log()打印出来inactive)。并且在某些情况下,它甚至不会释放鼠标光标,导致整个浏览器对鼠标事件没有响应;释放光标的唯一方法是在浏览器窗口之外单击并再次单击浏览器)。


我尝试过的其他事情:

window.addEventListener( 'focus', function() {...} );
document.addEventListener( 'focus', function() {...} );
document.body.addEventListener( 'focus', function() {...} );
document.getElementsByTagName('body')[0].addEventListener( 'focus', function() {...} );

问题: .addEventListener()这些元素在 IE 中根本不支持方法!嘎!


奖励:
您中观察力越强的人可能会说:“嘿,为什么不检测 Unity 对象本身上的鼠标单击事件并忽略该blur事件.live().bind()事件。” 试过了。IE也不喜欢它。它完全忽略该事件并说这些事件不适用于该对象。

所以我的 Javascript 专家。我不知道如何以一种优雅的方式最好地解决这个问题。任何指针将不胜感激。

4

1 回答 1

1

问题解决了。在 Unity3d 的论坛上提供了一个解决方案,埋在某处...... http://forum.unity3d.com/threads/27516-Mouse-input-possible-from-different-tab

它的要点是:框架并不总是答案。回到根源。

我忘记了.addEventListener()不是 IE 原生的,.attachEvent()是。因此,如果我在检测到 IE 时将所有事件侦听器替换为特定于 IE 的事件侦听器,那么我上面的代码就会起作用。

所以修改后的代码如下:

if ( navigator.appName == 'Microsoft Internet Explorer' ) {
    GetUnity().attachEvent( 'onmouseover', onFocus, false );
    GetUnity().attachEvent( 'onfocusin', onFocus, false );
    GetUnity().attachEvent( 'onmouseout', onBlur, false );
} else {
    // Netscape, Firefox, Mozilla, Chrome and Safari.
    GetUnity().addEventListener( 'mouseover', onFocus, false );
    GetUnity().addEventListener( 'focus', onFocus, false );
    GetUnity().addEventListener( 'mouseout', onBlur, false );
}

function onFocus() {
    NAMESPACE.WindowStatus( 'active' );
}

function onBlur() {
    NAMESPACE.WindowStatus( 'inactive' );
}

要真正做到这一点,您必须在unityobject.embedUnity()方法的回调函数中制作事件附件。如果您尝试在加载 Unity 之前附加事件,浏览器会报错GetUnity()nullor undefined

希望这可以帮助有人在同样的问题上挠头。

于 2011-04-08T08:19:56.540 回答