2021-09-17

最近项目需求,要用Unity打包成WebGL网页版,我在此简单说下遇到的坑!!!,本人用的是2018.3.0f2版本
1.字体问题
引擎自带的字体,打包之后,在网页上是显示不出来的,此时需要我们导入一个新字体样式即可解决
2.材质问题
如果在场景中或者脚本中使用了自定义的Shader,这时我们在打包之前,把这个Shader添加到Graphics设置中,如下图所示:
WebGL材质设置
3.UI布局问题
个人建议:我们在做UI锚点选择时,尽量选择统一,不要出现一套UI界面上多个锚点定位的问题,要不然我们在自适应窗口化时,有的UI会重叠到一起,影响视觉效果
4.输入不了中文问题
打包后,我们会发现输入不了中文,What?,是不是很奔溃?不过在我的执着的小心脏面前,它屈服了.
下面是我的解决办法:
4.1第一步

var WebGLInputField = {
	//打开输入框
  ShowInputFieldDialog:function(defaultValue){
  
      try {
          defaultValue = Pointer_stringify(defaultValue);
      } catch (e) {
		  alert(e);
		  return;
      }

      if(!document.getElementById("nativeInputDialog")) {
	      var element = document.createElement('div');
          // setup html
          var html = '<div id="nativeInputDialog" style="background:transparent; width:0%; height:0%; margin: 0; padding: 0; position: absolute; z-index:888;">' +
              '<input id="nativeInputDialogInput" type="text" style="border: none; background: none; width:0; height:0;left: 0; top:0;color: white; outline: none; display: block; position: relative; font-size: 10px; ">' +
              '</div>';
		  element.innerHTML = html;
		  document.body.appendChild(element);
		  
		  var m_nativeInputDialogInput = document.getElementById("nativeInputDialogInput");
		  m_nativeInputDialogInput.onkeypress  = function (event) {
			  //点击回车键,隐藏输入框
              if (event.keyCode == 13) {
				  document.getElementById("nativeInputDialog").style.display="none";
              }
          };
		  
		  document.onmousemove=function(event){
		     event = event||window.event;
			 document.getElementById("nativeInputDialog").style.left = event.clientX + 'px';
			 document.getElementById("nativeInputDialog").style.top = event.clientY + 20 + 'px';
		  }
      }
	  var m_nativeInputDialog = document.getElementById("nativeInputDialogInput");
	  m_nativeInputDialog.value = defaultValue;
	  document.getElementById("nativeInputDialog").style.display="";
      document.getElementById("nativeInputDialogInput").focus();
	  
  },
  //隐藏输入框
  HideInputFieldDialog :function(){
	 document.getElementById("nativeInputDialog").style.display="none";
  },
  IsInputFieldDialogActive:function(){
     var nativeDialog = document.getElementById("nativeInputDialog" );
     if(!nativeDialog ){
        return false;
     }
     return ( nativeDialog.style.display != 'none' );
  },
  GetInputFieldValue:function(){
    var elem = document.getElementById("nativeInputDialogInput");
    var returnStr = elem.value;
    var bufferSize = lengthBytesUTF8(returnStr) + 1;
    var buffer = _malloc(bufferSize);
    stringToUTF8(returnStr, buffer, bufferSize);
    return buffer;
  },
   GetInputFieldCursortPosition:function  () {
    var dialog = document.getElementById("nativeInputDialogInput");
    var index = dialog.selectionStart;
    return index;
  },
  GetInputFieldCursortFocusPosition:function  () {
    var dialog = document.getElementById("nativeInputDialogInput");
    var index = dialog.selectionEnd;
    return index;
  },
  SetInputFieldCursortPosition:function  (selectionStart,selectionEnd) {
    var elem = document.getElementById("nativeInputDialogInput");
    var val = elem.value
    var len = val.length
 
    // 超过文本长度直接返回
    if (len < selectionStart || len < selectionEnd) return;
	
    setTimeout(function() {
        elem.focus()
        if (elem.setSelectionRange) { // 标准浏览器
			elem.setSelectionRange(selectionStart, selectionEnd); 
        } 
    }, 10)
}
	 
};
mergeInto(LibraryManager.library , WebGLInputField );

以上代码以 .jslib 结尾保存,放到Plugins文件夹下
4.2 第二步

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using System.Runtime.InteropServices;
using System;

public class WebGLInputField : InputField
{
#if UNITY_WEBGL && !UNITY_EDITOR
    [DllImport("__Internal")]//显示对话框
    private static extern void ShowInputFieldDialog(string text);
    [DllImport("__Internal")]//隐藏对话框
    private static extern void HideInputFieldDialog();
    [DllImport("__Internal")]//对话框是否显示中
    private static extern bool IsInputFieldDialogActive();
    [DllImport("__Internal")]//获取对话框的数据
    private static extern string GetInputFieldValue();
    [DllImport("__Internal")]//获取光标选中坐标(起点点)
    private static extern int GetInputFieldCursortPosition();
    [DllImport("__Internal")]//获取光标选中坐标(终点)
    private static extern int GetInputFieldCursortFocusPosition();
    [DllImport("__Internal")]//设置光标选择
    private static extern void SetInputFieldCursortPosition(int selectionStart, int selectionEnd);
    private bool captureAllKeyboardInput
    {
        get
        {
            return WebGLInput.captureAllKeyboardInput;
        }
        set
        {
            WebGLInput.captureAllKeyboardInput = value;
        }
    }
    private float timer;
    private Coroutine overlayhtml;
    private Coroutine setposCoroutine;

    public override void OnPointerClick(PointerEventData eventData)
    {
        base.OnPointerClick(eventData);

        captureAllKeyboardInput = false;

        ShowInputFieldDialog(text);

        if (IsInputFieldDialogActive() && overlayhtml != null)
        {
            //更新光标
            if(setposCoroutine != null)
            {
                SetSelection();
            }
            else
            {
                setposCoroutine = StartCoroutine(DelySetPostion());
            }
        }
        else
        {
            //打开html端的输入框
            overlayhtml = StartCoroutine(this.OverlayHtmlCoroutine());
        }
    }

    private IEnumerator DelySetPostion()
    {
        captureAllKeyboardInput = true;
        yield return null;
        SetSelection();
        captureAllKeyboardInput = false;
        setposCoroutine = null;
        System.GC.Collect();
    }

    private IEnumerator OverlayHtmlCoroutine()
    {
        yield return DelySetPostion();
        //设置选中对象为
        while (IsInputFieldDialogActive() && isFocused)
        {
            yield return null;
            var textFromHtml = GetInputFieldValue();
            if (textFromHtml != this.text)
            {
                this.text = textFromHtml;
                ForceLabelUpdate();
                yield return null;
            }

            if (!captureAllKeyboardInput && setposCoroutine == null && !Input.GetMouseButton(0))
            {
                UpdateCaretPositions();
                yield return null;
            }
        }
        HideInputFieldDialog();
        EventSystem.current.SetSelectedGameObject(null);
        captureAllKeyboardInput = true;
        overlayhtml = null;
        System.GC.Collect();
    }

    /// <summary>
    /// 设置选中区域
    /// </summary>
    private void SetSelection()
    {
        var selectionStart = selectionAnchorPosition < selectionFocusPosition ? selectionAnchorPosition : selectionFocusPosition;
        var selectionEnd = selectionAnchorPosition > selectionFocusPosition ? selectionAnchorPosition : selectionFocusPosition;
        SetInputFieldCursortPosition(selectionStart, selectionEnd);
    }

    /// <summary>
    /// 从html更新caretPosition
    /// </summary>
    private void UpdateCaretPositions()
    {
        var cpos = GetInputFieldCursortPosition();
        var fpos = GetInputFieldCursortFocusPosition();
        var changed = false;
        if (cpos != caretPosition)
        {
            caretPosition = cpos;
            changed = true;
        }
        if (fpos != selectionFocusPosition)
        {
            selectionFocusPosition = fpos;
            changed = true;
        }

        if (changed)
        {
            ForceLabelUpdate();
        }
    }

#endif
    //注意Time.timeScale = 0 会无法更新信息
    //private void Update()
    //{
    //    if(Input.GetMouseButtonDown(1) && isFocused)
    //    {
    //        Debug.Log("caretPosition:" + caretPosition);//光标坐标
    //        Debug.Log("currentSelectionState:" + currentSelectionState);//选中状态
    //        Debug.Log("selectionAnchorPosition:" + selectionAnchorPosition);//选择起点
    //        Debug.Log("selectionFocusPosition:" + selectionFocusPosition);//选择结束点
    //    }
    //}
}

用这个脚本替换系统自带的 InputField 组件 即可
经过这两步以后,就可以实现输入中文了

5.AB包问题
相信我们在做资源更新时,会用到AB包,不过在打包成WebGL时,我们要注意了,就是我们在设置PlayerSettings时,Other Settings–>Strip Engine Code 这个选项一定不要勾选,否则加载不出来资源.

6.播放音频问题
个人建议:使用系统自带的播放音频的组件去播放音频,不要使用一些文字转语音的插件,很多这类插件是不支持网页版的.
7.模板
个人建议:在我们发布webgl时,我们可以自定义自己喜欢的模板,发布的时候选择它,这样的话我们就不用每次发布完后,还要再去调整一遍样式,如下图所示
选择模板
至于具体的怎样去创建模板,我就不再一一讲解了,官网上有教程,需要的小伙伴可以出查看

至此 我把我这个项目中遇到的一些问题写出来,供大家参考,我们相互学习,共同进步.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

weixin_44214357

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值