本記事の内容
・WebGLのInputFieldで日本語入力をするための対処方法
・WebGLNativeInputFieldを使用する場合、Unity2023以降でのスクリプト書き換え内容
WebGLではInputFieldで日本語入力が使えない
WebGLあるある:日本語入力出来ない
UnityのWebGLでビルドすると、InputFieldで日本語入力が出来なくて焦る人は多いと思います。
日本語に対応する対処法はいくつかあるので、方法を紹介します。
WebGLで日本語を入れる対処法
Unity公式のアセットを使う
Unity公式から、以下のGitHubで、回避するためのInputFieldが配布されています。
日本語の導入方法もあるのでわかりやすいです。
特徴としては、入力時にゲームが一度完全に止まり、入力画面が表示される仕様になっています。
ですが、このアセットを使った場合、問題が2つ発生しました。問題の解決策も書いておきます。
スマホ限定:プロンプトをキャンセルすると画面が勝手にアップされてしまう
スマホから、Safariでブラウザを開き、ビルドファイルを遊べるURLにアクセスし、Input Fieldをタップすると画面が勝手にスケールアップされ、戻らなくなりました。
画面が大きい端末では発生しなかったのですが、画面の小さいiPhone(SE2)のSafariで発生しました。また、OKボタンのときではなく、キャンセルボタンのときだけ発生しました。
完全に憶測ですが、Safari側で入力項目がある場合、文字が小さいからアップしといたろ!といういらない配慮をしてくれるからなのかと💩
フォントサイズを大きくもしてみたのですが、回避出来なかったので、ゲームを配置しているサイトのHTMLに以下のメタタグを仕込むことで強引に回避しました。
これは、スケールアップを強引に止めるためのコードです。
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
また、DialogTypeに「Prompt Popup」と「Overlay html」があるのですが、「Overlay html」はスマホでは動きませんでした。
また、WebGLNativeInputで使われているプロンプト画面は、端末ネイティブのものを呼び出しているので、プロンプト自体をカスタムする(キャンセルボタンを消すなど)ことは出来ませんでした。
Unity2023以降:ビルドすると、ブラウザでエラーが出る
ビルド時にブラウザで以下のエラーが出ました。
An error occurred running the Unity content on this page. See your browser JavaScript console for more info. The error was:
ReferenceError: writeStringToMemory is not defined
正直なことを書くと、ChatGPT君に聞いた答えを丸パクリしたら直りました。javascirptは詳しくないので...。
Unity2023から古いAPIが削除されたようで、WebGL Native InputFieldはそれを使っていたのが原因とのこと。
以下のパスにあるJavaScriptファイルを、以下のコードで書き換えたら直りました。
WebGLNativeInputField > Plugins > WebGL >WebNativeDialog(パズルピースみたいなアイコン)
具体的には元のコードにある、writeStringToMemory
と、writeStringToMemory
がNGみたいです。
var WebNativeDialog = {
NativeDialogPrompt: function (title, defaultValue) {
defaultValue = UTF8ToString(defaultValue);
title = UTF8ToString(title);
var result = window.prompt(title, defaultValue);
if (!result) {
result = defaultValue;
}
var buffer = _malloc(lengthBytesUTF8(result) + 1);
stringToUTF8(result, buffer, lengthBytesUTF8(result) + 1);
return buffer;
},
SetupOverlayDialogHtml: function (title, defaultValue, okBtnText, cancelBtnText) {
title = UTF8ToString(title);
defaultValue = UTF8ToString(defaultValue);
okBtnText = UTF8ToString(okBtnText);
cancelBtnText = UTF8ToString(cancelBtnText);
if (!document.getElementById("nativeInputDialogInput")) {
// setup css
var style = document.createElement('style');
style.setAttribute('id', 'inputDialogTextSelect');
style.appendChild(document.createTextNode('#nativeInputDialogInput::-moz-selection { background-color:#00ffff;}'));
style.appendChild(document.createTextNode('#nativeInputDialogInput::selection { background-color:#00ffff;}'));
document.head.appendChild(style);
}
if (!document.getElementById("nativeInputDialog")) {
// setup html
var html = '<div id="nativeInputDialog" style="background:#000000;opacity:0.9;width:100%;height:100%;position:fixed;top:0%;z-index:2147483647;">' +
' <div style="position:relative;top:30%;" align="center" vertical-align="middle">' +
' <div id="nativeInputDialogTitle" style="color:#ffffff;">Here is title</div>' +
' <div>' +
' <input id="nativeInputDialogInput" type="text" size="40">' +
' </div>' +
' <div style="margin-top:10px">' +
' <input id="nativeInputDialogOkBtn" type="button" value="OK" onclick="">' +
' <input id="nativeInputDialogCancelBtn" type="button" value="Cancel" onclick ="">' +
' <input id="nativeInputDialogCheck" type="checkBox" style="display:none;">' +
' </div>' +
' </div>' +
'</div>';
var element = document.createElement('div');
element.innerHTML = html;
// write to html
document.body.appendChild(element);
// set Event
var okFunction =
'document.getElementById("nativeInputDialog").style.display = "none";' +
'document.getElementById("nativeInputDialogCheck").checked = false;' +
'document.getElementById("canvas").style.display="";';
var cancelFunction =
'document.getElementById("nativeInputDialog").style.display = "none";' +
'document.getElementById("nativeInputDialogCheck").checked = true;' +
'document.getElementById("canvas").style.display="";';
var okBtn = document.getElementById("nativeInputDialogOkBtn");
okBtn.setAttribute("onclick", okFunction);
var cancelBtn = document.getElementById("nativeInputDialogCancelBtn");
cancelBtn.setAttribute("onclick", cancelFunction);
}
document.getElementById("nativeInputDialogTitle").innerText = title;
document.getElementById("nativeInputDialogInput").value = defaultValue;
document.getElementById("nativeInputDialogOkBtn").value = okBtnText;
document.getElementById("nativeInputDialogCancelBtn").value = cancelBtnText;
document.getElementById("nativeInputDialog").style.display = "";
},
HideUnityScreenIfHtmlOverlayCant: function () {
if (navigator.userAgent.indexOf("Chrome/") < 0) {
document.getElementById("canvas").style.display = "none";
}
},
IsRunningOnEdgeBrowser: function () {
return navigator.userAgent.indexOf("Edge/") >= 0;
},
IsOverlayDialogHtmlActive: function () {
var nativeDialog = document.getElementById("nativeInputDialog");
return nativeDialog && nativeDialog.style.display != 'none';
},
IsOverlayDialogHtmlCanceled: function () {
var check = document.getElementById("nativeInputDialogCheck");
return check && check.checked;
},
GetOverlayHtmlInputFieldValue: function () {
var inputField = document.getElementById("nativeInputDialogInput");
var result = inputField && inputField.value ? inputField.value : "";
var buffer = _malloc(lengthBytesUTF8(result) + 1);
stringToUTF8(result, buffer, lengthBytesUTF8(result) + 1);
return buffer;
}
};
mergeInto(LibraryManager.library, WebNativeDialog);
WebGL Input
こちらの配布されているプラグインでも、日本語入力が出来ます。
ただ、モバイルで実行すると、入力パネルが消えなくなったり、入力した文字が大きくなったりと思わぬ挙動が発生しました。
ただ、PCブラウザで動かす分には問題なかったです。
まとめ
WebGLのInput Field問題は、Unity6で解決するのかと思っていましたが(正式にWebGLのモバイルにも対応したので)、逆に手間が増えてしまいました。ぜひとも、これは公式対応してほしいところです。
それでは、素敵なゲーム制作ライフを!
コメント