IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> 2021-09-17 -> 正文阅读

[游戏开发]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时,我们可以自定义自己喜欢的模板,发布的时候选择它,这样的话我们就不用每次发布完后,还要再去调整一遍样式,如下图所示
选择模板
至于具体的怎样去创建模板,我就不再一一讲解了,官网上有教程,需要的小伙伴可以出查看

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

  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2021-09-18 10:33:04  更:2021-09-18 10:33:08 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/17 12:11:59-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码