Escape input key with unity3d WEB GL build - unity3d

I creating WEB GL game. Game menu is shown by the following code:
Input.GetKeyUp(KeyCode.Escape)
It works fine in unity and in the windows build. In the browser, escape pressing is intercepted by browser and the menu is not displayed.
Is it possible to make this code working in WEB GL build? What is the standart "meny button" for WEB GL games?

It should be working because
From Unity Manual webgl input : By default, Unity WebGL will process all keyboard input send to the page, regardless of whether the WebGL canvas has focus or not.
It could be that you disabled WebGLInput.captureAllKeyboardInput (Which is enabled by default) In that case just enable that and it should work.

The Escape Button is used by default for exiting fullscreen mode, maybe that's causing the issue. I would suggest to use the Input Manager ( https://docs.unity3d.com/Manual/class-InputManager.html ) and define a button using Escape as the positive button.

As #pasotee mentioned, the Escape key could be consumed already. By the Browser, as well as by the Unity Player, as for example the F1 key is used by Chrome to open the Help Tab. Escape is definitely used by the Unity Player to exit its Fullscreen mode.
So the short answer is. No, you can't.
Unity is listening to all key by default, true, but never gets the events when the upper lying application, like the browser, doesn't send it to the Canvas or the executing environment - aka the Unity3d Player doesn't send it down to your code. Or in this case, they should really fix the manual to "[..] all buttons, except Escape and browser related Hotkeys":
https://docs.unity3d.com/Manual/webgl-input.html
The long answer is, you might intercept the 'Escape' key event within JavaScript and pass a function call into the Unity Player like mentioned here:
jQuery
$(document).on('keyup',function(evt) {
if (evt.keyCode == 27) {
alert('Esc key pressed.');
}
});
https://jsfiddle.net/MQHVa/1/
Vanilla JS
var msg = document.getElementById('state-msg');
document.body.addEventListener('keypress', function(e) {
if(e.key == "Escape"){
msg.textContent += 'Escape pressed:'
}
});
https://jsfiddle.net/etcjwaf5/
And in the end you'll need this information, to call Unity from Javascript:
SendMessage('MyGameObject', 'MyFunction');
SendMessage('MyGameObject', 'MyFunction', 5);
SendMessage('MyGameObject', 'MyFunction', 'MyString');
https://docs.unity3d.com/Manual/webgl-interactingwithbrowserscripting.html
And the very last thing is to have a GameObject in your loaded Scene that provides the function for doing, whatever you desired to be done.
Bare in mind, that if you don't cancel distribution of the Escape key event it will be send to the UnityPlayer which triggers it to exit fullscreen mode! And you might not be able to prevent Unity from consuming this event anyway, so remember WebGLInput.captureAllKeyboardInput member.

Related

How do you automatically focus on an inputfield when opening/activating the UI in Unity3d?

I am making a game where you must open or activate the UI with the space bar. Now, this works perfectly fine, but it is pretty annoying that every time you open the UI you must click on the inputfield to write in it. Is there any way around this? So is there a way to open or activate the UI without having to click on the field to be able to write in it?
I looked for YouTube videos and tried to find similar problems in other forums, but wasn't able to find a script, nor was I able to find some Unity settings to do so.
You could use e.g.
private class SelectOnEnable : MonoBehaviour
{
private void OnEnable()
{
EventSystem.current.SetSelectedGameObject(null);
EventSystem.current.SetSelectedGameObject(gameObject);
}
}
and attach it to whatever object that should become the selected one everytime it is enabled. See EventSystem.SetSelectedGameObject
Can't test it right now but it might still require the User to hit Enter in order to also actually set the Input field into edit mode. The upper line only sets it as selected UI element (similar to using TAB in a browser).
Otherwise I think you would go through
yourInputField.DeactivateInputField()
yourInputField.ActivateInputField();
to directly set it active. See InputField.ActivateInputField. Might have to do both in combination - again can't test right now ;)
Thank you very much, derHugo! Everything works like a charm now! You saved me a lot of time. Referring to your last comment, I used both of them, and it seems to work very well for me. Here is the code I used:
`private void OnEnable()
{
EventSystem.current.SetSelectedGameObject(gameObject);
GameManager.GetComponent().inputFieldInMainUi.ActivateInputField();
EventSystem.current.SetSelectedGameObject(null);
GameManager.GetComponent<InputFieldComparision>().inputFieldInMainUi.DeactivateInputField();
}`

SceneManager LoadScene not working in editor playmode

as the title says I have an issue loading a scene when in playmode in the editor.
The workflow of my game is as follows:
Initializing (works fine)
There is an empty scene that creates some global game objects that will exist during the entire runtime.
MainMenu (works fine)
After the Initializing is done it loads the MainMenu scene. I can interact with the scene and everything is nice.
Connect to game server (works fine)
In the main menu I have an option to connect to a game server (a dedicated server application I created on my own)
Establishing the connection and sending the login works well.
Character selection (not working)
After the login on the server I get the resonse to select a character. (This works as expected.)
Then I'm going to handle this response by opening the character selection scene.
And here I have the issue. In Playmode inside the editor the handler method is executed (verifyed by debug logs) but the scene is not loaded actualy.
When I build the game and run the created .exe and follow the exact same steps the character selection scene is loaded and shown as expected.
I searched the documentation and also the web but did not find any similar issues (maybe I still missed something)
So my question is as follows:
How do I get the scene to also load in the editor playmode? My approach seems not to be totaly wrong as it works after build.
Here is the code snippet that should load the scene:
private void MessageRecived(object sender, GNL.ResponseMessageEventArgs e)
{
GameEventMessage message = this.eventManager.MessageHandler.ParseMessage(e.Message);
Debug.Log($"Recived message with type {message.Type}");
switch (message.Type)
{
case GameEvent.CharacterSelectionRequired:
Debug.Log($"Handle character creation 01");
this.HandleCharacterSelectionRequried(message);
break;
default:
break;
}
}
private void HandleCharacterSelectionRequried(GameEventMessage eventMessage)
{
Debug.Log($"Handle character creation 02");
SceneManager.LoadScene("CharacterCreation");
}
All three Debug.Log statements are executed. Only the LoadScene isn't working in the editor playmode.
IMPORTANT ADDITION
After further testing I have to mention that the network communication is done in a seperate thread. From this thread when a new message arrives an eventHandler is called.
This is where the Method is added to the Event handler:
this.client = new GNL.GameClient(System.Net.IPAddress.Parse(host), port);
this.client.AnnounceRecivedMessage += this.MessageRecived;
this.clientNetwork = new Thread(this.client.Start);
clientNetwork.Start();
And this is the definition of the eventHandler:
public event EventHandler<ResponseMessageEventArgs> AnnounceRecivedMessage;
IMPORTANT ADDITION - Part 2
I just discovered that, it works on a normal build but not when selecting "development build" in the build settings.
This is really annoying as I have to build the game every time I made a change to test it.
I'm thankful for any help and suggestions.
After much more debugging and testing I figured out that this issue indeed is a threading issue.
Deep in the debugger I found the exception I would have expected for a threading issue. So I will have to change my implementation here.
But still there is an inconsistence in how threads are handled in Unity when running the game with debugging tools enabled (playmode in editor and development build) and with them disabled (normal build).
AFAIK, you can't switch between scenes in the editor. Unity Editor only works to edit and play the opened scene.
If you want to test some parts of the workflow, create functions dedicated to the editor (you can use #if UNITY_EDITOR) to test your scenes without the previous character selection.

AirConsole Unity plugin - WebGL build does not work while Unity debugger works

We've created a small demo of Unity3D with AirConsole-plugin which is working in Unity debugger. (If I press play, the browser opens, sometimes it works, sometimes it doesn't. If it doesn't, one can restart Unity and then it works.)
If we create a release or a developer build, it does no longer work. It will load the image correctly, but the controllers (virtual+phone) stay 'loading' most of the time. Sometimes they reach the first correct HTML page, but then the message they send doesn't seem to arrive on the screen-side.
When I click the 'Open Exported Port' after the build, it doesn't work too, except for once.
One error message I got once:
"Uncaught TypeError: Cannot read property 'postQueue' of undefined"
This error message appears always:
"pre-main prep time: 176 ms UnityLoader.js:1
Module.printErr # UnityLoader.js:1"
Do you know what these error messages mean?
I've tried a lot, but this seems to solve the problem: Be sure to attach the event listeners in the Awake method, as they do in basic example application.
public class AirConsoleService : MonoBehaviour
{
void Awake()
{
// register events
AirConsole.instance.onReady += OnReady;
AirConsole.instance.onMessage += OnMessage;
AirConsole.instance.onConnect += OnConnect;
AirConsole.instance.onDisconnect += OnDisconnect;
// etc. ...
}
// etc. ...
}
My problem was that my AirConsoleService was static and not a MonoBehaviour to be sure that there is only one instance of AirConsoleService. It works perfectly for the debug 'play' mode, but in the release build, the AirConsole somehow does not know the deviceID which sent the message (this means, we get -1 from method ConvertDeviceIdToPlayerNumber. And this explains why the controllers don't get any signal from the screen.
My solution: I've attached it as a component to the AirConsole object.
Further notes:
Anti-Virus may block content.
Your PC/server has to be fast.
During development, log the deviceID and the playerID and the current active deviceIDs.
Often restart Unity or the integrated webserver of the plugin

How can I disable facebook's new-message popup?

I know the standard way of handling the wmode problem is to register a callback that pauses the flash app and replaces the flash area with an image while the flash object is hidden.
What I'm trying to avoid is the flash disappearing in mid-game because of the facebook-chat auto-flyout when somebody sends a message the user (user's friends can essentially pause the user's game remotely, simply by sending them an instant message).
It seems as if Angry Birds Friends and Zynga's Ruby Blast Adventure have solved this problem somehow. These games run on stage3d so their wmode is set to 'direct', and when an instant message is received, facebook shows only a small new-message-indicator instead of displaying the full messages-dialog right away.
I can't figure out how they've managed to do that.
For me, facebook always seems to pop up the messaging as soon as a message is received.
The game is in stage3d so having a wmode of 'direct' is a must.
Any help would be greatly appreciated.
I'm battling with the same issue, except imo the perfect solution would be to show both the chat (and other facebook menus) and the stage3d flash at the same time. It seems that setting the element containing the flash, e.g. div as:
display: block !important;
visibility: visible !important;
does the trick, but I'm not really confident that is the perfect solution.. It seems that on some browser/OS combination some (Facebook invoken) ui stuff is now shown behind the flash at least partially. Would appreciate a lot for "an official correct answer(tm)".
You can write a listener function to be called when your game loses or regains focus, and register it with the Facebook environment by passing it to FB.init() as the hideFlashCallback parameter. The listener will be passed a parameters dictionary which will contain a key called state, which will be set to opened if you should be hiding your game.
In that case, the listener should call the Flash app's exportScreenshot method, use the Base64-encoded image data to create a data URL, and make that the src of an img element; it should move your app's containing element offscreen using the FB.hideFlashElement method in the JS SDK, and replace it with that img. If the parameters dictionary passed to the listener does not have state: "opened" then, instead, bring your Flash app back onscreen using FB.Canvas.showFlashElement.
You can find more information here: https://developers.facebook.com/docs/games/gamesonfacebook/optimizing#handlingpopups

Prevent iPhones webkit from opening a new browser window (and thus exiting fullscreen) when clicking an `rel="external"` link

Opening my mobile webpage from my homescreen (after adding it to my homescreen), it starts in fullscreen mode, so far so good.
After logging in (form/submitbutton), the 'app' is still in fullscreen mode, which is also the desired result.
Now, when I click a link that has the rel="external" attribute, webkit opens a new window in Safari, so it exits the fullscreen 'app' I started from my homscreen, I would like it to stay in fullscreen mode.
data-ajax="false" has te same result. Removing data-ajax="false" and rel="external" will not exit fullscreen, but this way you can't link to a multi-page document (1 document with different data-role="page").
Does anyone has the same problem, or even better, a solution?
I do not really care about the transitions, I just want the webpage to remain in fullscreen mode, (the user has to log in again when the new window has opened).
iPhone 3gs
M_webkit / 5.0.2
Why not create a script that pulls out the href and goes to the new url via javascript.
If you use jQuery it's as simple as:
$("a[rel='external']").bind("click",
function() {
if (this.href) {
location.href = this.href;
return false;
}
});
Without jquery you'll need to use object detection and attach a click event to it with the same logic inside the anonymous function above.