由于Unity WebGL本身不能很好的支持中文输入,拷贝,输入法跟随,然后网上找的插件,大多不令人满意,于是决定自己开发一个~
//2020年2月26日修改:
由于之前1.0版本的插件在Unity2019.2.4版本中打包,没有在低版本测试,导致有些使用低版本(2019以下的)的朋友无法使用,会出现missing的问题,Unity的高低版本在UI和WebGL也存在点差异,现在我重新打包一个1.1版本的插件,感谢大家的评论~
自研插件名称:ChineseInputWebGL1.1.unitypackage 插件下载
支持功能:
1.中英文输入
2.支持光标移动中间插入输入
3.输入法跟随
4.支持Ctrl+C(拷贝),Ctrl+V(粘贴),Ctrl+X(裁剪)等键盘操作
5.支持WebGL全屏
主要思路:在unity WebGL打包浏览页面的对应位置,动态创建一个Html的Input控件,去实现功能
主要代码
js部分:
var ChineseInputWebGL = {
$input:null,
$canvas:null,
$unityContainer:null,
$webglcontent:null,
$unityGameObjectName : "",
$unityInputID: "",
$Inputing: function()
{
if(unityGameObjectName!=null&&unityInputID!=null && input != null)
{
var strvalue = unityInputID+"|"+input.value+"|"+input.selectionStart;
SendMessage(unityGameObjectName, "OnInputText", strvalue);
}
},
$InputEnd: function()
{
if(unityGameObjectName!=null&&unityInputID!=null && input != null)
{
SendMessage(unityGameObjectName,"OnInputEnd",unityInputID.toString());
}
document.onkeydown=null;
},
InputShow: function(GameObjectName_,inputID_,v_,fontsizeT_,indexStr_,inputRectStr_)
{
var GameObjectName = Pointer_stringify(GameObjectName_);
var inputID = Pointer_stringify(inputID_);
var v = Pointer_stringify(v_);
var fontsizeT = Pointer_stringify(fontsizeT_);
var indexStr=Pointer_stringify(indexStr_);
var inputRectStr = Pointer_stringify(inputRectStr_);
var indexArr=indexStr.split("|");
var startIndexT = indexArr[0];
var endIndexT = indexArr[1];
var inputRectArr=inputRectStr.split("|");
var posX = inputRectArr[0];
var posY = inputRectArr[1];
var width = inputRectArr[2];
var height = inputRectArr[3];
if(input==null){
input = document.createElement("input");
input.type = "text";
input.id = "ChineseInputWebGLId";
input.name = "ChineseInputWebGL";
input.style = "visibility:hidden;";
input.oninput = Inputing;
input.onblur = InputEnd;
//document.body.appendChild(input);
document.getElementsByClassName("webgl-content")[0].appendChild(input);//需要放在这个下面,这样就方便计算在=相对canvas下的位置
//document.getElementById("#canvas").appendChild(input);//需要放在这个下面,这样就方便计算在=相对canvas下的位置
input.style.pointerEvents = "none";//不遮挡鼠标事件
//input.zIndex=1000;//设置层级使不被遮挡
}
if(canvas==null)
{
canvas = document.getElementById("#canvas");
}
this.screenSizeX=canvas.width;
this.screenSizeY=canvas.height;
if(unityContainer==null)
{
unityContainer = document.getElementById("unityContainer");
}
this.unityScreenSizeX=unityContainer.style.width.replace("px","");
this.unityScreenSizeY=unityContainer.style.height.replace("px","");
if(webglcontent==null)
{
webglcontent = document.getElementsByClassName("webgl-content")[0];
}
this.webglcontentSizeX=webglcontent.clientWidth;
this.webglcontentSizeY=webglcontent.clientHeight;
var offsetX=(this.screenSizeX-this.webglcontentSizeX)/2;
var offsetY=(this.screenSizeY-this.webglcontentSizeY)/2;
//alert(posX+"-"+this.screenSizeX+"-"+this.unityScreenSizeX+"-"+this.webglcontentSizeX+"-"+offsetX)
//alert(posY+"-"+this.screenSizeY+"-"+this.unityScreenSizeY+"-"+this.webglcontentSizeY+"-"+offsetY)
if(offsetX>0)
{
posX=posX-offsetX;
}
if(offsetY>0)
{
posY=posY-offsetY;
}
input.style.width=width+"px";
input.style.height=height+"px";
input.style.left =posX+"px";//左边距
//posY=posY-40;//测试
input.style.top =posY+"px";//上边距
input.value = v;
input.style.fontSize=fontsizeT+"px";
unityGameObjectName = GameObjectName;
unityInputID = inputID;
input.style.position='absolute';
input.style.visibility = "visible";
input.style.opacity = 0;
input.focus();
input.selectionStart = startIndexT;
input.selectionEnd = endIndexT;
//console.log("InputShow:"+startIndexT+"|"+endIndexT);
document.onkeydown = function (event) {
event = event || window.event; //IE suckes
if (event.keyCode == 65 && event.ctrlKey) {//捕捉Ctrl+A事件
SendMessage(unityGameObjectName, "SelectAll");
}
else if (event.keyCode == 37) {//左方向键
var selectionindex=input.selectionStart-1;
var strvalue = unityInputID+"|"+input.value+"|"+selectionindex;
//console.log("左方向键:"+input.selectionStart+"|"+selectionindex);
SendMessage(unityGameObjectName, "OnInputText", strvalue);
}
else if (event.keyCode == 39) {//右方向键
var selectionindex=input.selectionStart+1;
var strvalue = unityInputID+"|"+input.value+"|"+selectionindex;
//console.log("右方向键:"+input.selectionStart+"|"+selectionindex);
SendMessage(unityGameObjectName, "OnInputText", strvalue);
}
}
}
};
C#部分:
#if UNITY_WEBGL && !UNITY_EDITOR
int selectStartIndex;//选择文本框中文字的起始位置
int selectEndIndex;//选择文本框中文字的结束位置
bool isFocus;
void Start()
{
inputField = GetComponent<InputField>();
InputWebGLManage.Instance.Register(gameObject.GetInstanceID(),this);
RectT = GetComponent<RectTransform>();
//添加unity输入框回调
inputField.onValueChanged.AddListener(OnValueChanged);
inputField.onEndEdit.AddListener(OnEndEdit);
//添加获得焦点回调
EventTrigger trigger = inputField.gameObject.GetComponent<EventTrigger>();
if (null == trigger)
trigger = inputField.gameObject.AddComponent<EventTrigger>();
EventTrigger.Entry e = new EventTrigger.Entry();
e.eventID = EventTriggerType.PointerDown;
e.callback.AddListener((data) => { OnFocus((PointerEventData)data); });
trigger.triggers.Add(e);
}
void Update()
{
if (isFocus)
{
if (inputField.selectionAnchorPosition <= inputField.selectionFocusPosition)
{
if (selectStartIndex != inputField.selectionAnchorPosition || selectEndIndex != inputField.selectionFocusPosition)
{
OnSelectRangeChanged(inputField.selectionAnchorPosition, inputField.selectionFocusPosition);
}
}
else
{
if (selectStartIndex != inputField.selectionFocusPosition || selectEndIndex != inputField.selectionAnchorPosition)
{
OnSelectRangeChanged(inputField.selectionFocusPosition, inputField.selectionAnchorPosition);
}
}
}
}
#region ugui回调
private void OnValueChanged(string arg0)
{
}
private void OnFocus(PointerEventData pointerEventData)
{
isFocus = true;
WebGLInput.captureAllKeyboardInput = false;
InputShowOP(inputField.text, inputField.selectionAnchorPosition + "|" + inputField.selectionFocusPosition);
}
public void OnSelectRangeChanged(int startIndex, int endIndex)
{
selectStartIndex = startIndex;
selectEndIndex = endIndex;
InputShowOP(inputField.text, selectStartIndex + "|" + selectEndIndex);
}
public void InputShowOP(string text, string indexStr)
{
//获取在Canvas下的位置
Canvas canvas = transform.GetComponentInParent<Canvas>();
float X = 0;
float Y = 0;
GetPosXY(canvas, transform, ref X, ref Y);
//左边距
float posX = Screen.width / 2 + X - RectT.rect.width * RectT.pivot.x;
//上边距
float posY = Screen.height / 2 - Y - RectT.rect.height * (1 - RectT.pivot.y);
string inputRectStr = posX + "|" + posY + "|" + RectT.rect.width + "|" + RectT.rect.height;
string fontsize = inputField.textComponent.fontSize.ToString();
InputWebGLManage.Instance.InputShow(gameObject.GetInstanceID().ToString(), text, fontsize, indexStr, inputRectStr);
}
private void OnEndEdit(string str)
{
isFocus = false;
}
///
/// 获取在Canvas下的位置
///
public void GetPosXY(Canvas canvas, Transform tran, ref float x, ref float y)
{
x += tran.localPosition.x;
y += tran.localPosition.y;
if (canvas.transform == tran.parent)
{
return;
}
else
{
GetPosXY(canvas, tran.parent, ref x, ref y);
}
}
#endregion
#region WebGL回调
public void OnInputText(string text,string selectIndexStr)
{
inputField.text = text;
try
{
int selectIndex= int.Parse(selectIndexStr);
inputField.selectionAnchorPosition = selectIndex;
inputField.selectionFocusPosition = selectIndex;
selectStartIndex = selectIndex;
selectEndIndex = selectIndex;
}
catch
{
inputField.selectionAnchorPosition = inputField.text.Length;
inputField.selectionFocusPosition = inputField.text.Length;
}
inputField.Select();
inputField.ForceLabelUpdate();
}
public void OnInputEnd()
{
WebGLInput.captureAllKeyboardInput = true;
//inputField.DeactivateInputField();
}
public void SelectAll()
{
inputField.selectionAnchorPosition = 0;
inputField.selectionFocusPosition = inputField.text.Length;
inputField.Select();
inputField.ForceLabelUpdate();
}
#endregion
#endif