Unity WebGL - Prevent From eating up all

2019-08-01 19:38发布

问题:

Unity 5.4

Building a Unity WebGL application (not a game) that handles all 3D content on the Unity side of things, and all the UI is built using HTML/CSS/JS. By default, WebGLInput.captureAllKeyboardInput is set to true, which causes any input fields that require keyboard (text) input to be broken, as any keyboard controls are automatically being eaten up by Unity rather than going to the input field. Doing

#if !UNITY_EDITOR && UNITY_WEBGL
WebGLInput.captureAllKeyboardInput = false;
#endif

fixes the issue with input fields, but causes unity to ignore ALL keyboard inputs, even after the element is focused, however adding

tabindex="1"

to the fixes it so that keyboard input on HTML input fields works when focused, and keyboard controls inside the Unity WebGL app works when focused as well. (this is all per the docs: https://docs.unity3d.com/ScriptReference/WebGLInput-captureAllKeyboardInput.html). So that's all working fine.

However, the Unity WebGL application is still causing issues with some input fields using MOUSE (not keyboard) controls. Namely I've noticed it on input type="range" fields (HTML5 sliders) and input type="number (using keyboard to type in numbers works, but mouse clicking up and down do not).

Is there any sort of workaround to fix this? I essentially need to prevent the Unity WebGL canvas to not automatically take all mouse inputs, unless the element is clicked/focused first (just like the way the keyboard controls work). Anything to change on the Unity side to fix this? Or do I need to write some custom JavaScript to handle all input and determine whether it's intended for the Unity scene or the HTML UI?

回答1:

I was having the same issue but I believe I've found a workaround! Originally I was just going to use OnApplicationFocus to toggle WebGLInput.captureAllKeyboardInput. But OnApplicationFocus doesn't work with WebGL builds of Unity so I'm doing this instead.

I have a script named "GameControl" on a GameObject also named "GameControl" in the first scene when the game is loaded.

// In the Start function of this script I call a function on the webpage to let it know that the game has loaded.
void Start () {
    #if (UNITY_WEBPLAYER || UNITY_WEBGL) && !UNITY_EDITOR
    try {
        Application.ExternalCall("GameControlReady");
    } catch (System.Exception e) {
        Debug.LogError("GameControlReady function not on webpage"+e);
    }
    #endif
}

// This function will be called from the webpage
public void FocusCanvas (string p_focus) {
    #if !UNITY_EDITOR && UNITY_WEBGL
    if (p_focus == "0") {
        WebGLInput.captureAllKeyboardInput = false;
    } else {
        WebGLInput.captureAllKeyboardInput = true;
    }
    #endif
}

On the webpage, I have the following javascript:

var gameReady = false;

// Called by Unity in GameControl's start function
function GameControlReady () {
    gameReady = true;
}

function FocusCanvas(focus) {
    if (gameReady) {
        SendMessage("GameControl", "FocusCanvas", focus);
    }
}

And in the head section of the webpage I have the following

<script type='text/javascript'>
    document.addEventListener('click', function(e) {
        if (e.target.id == "canvas") {
            // Clicked on canvas
            FocusCanvas("1");
        } else {
            // Clicked outside of canvas
            FocusCanvas("0");
        }
    });
</script>