当前位置: 首页 > news >正文

【Unity3D日常开发】Unity3D中适用WEBGL打开Window文件对话框打开/上传文件

推荐阅读

  • CSDN主页
  • GitHub开源地址
  • Unity3D插件分享
  • QQ群:398291828
  • 小红书
  • 小破站

大家好,我是佛系工程师☆恬静的小魔龙☆,不定时更新Unity开发技巧,觉得有用记得一键三连哦。

一、前言

Unity3D发布的WEBGL程序是不支持直接的I/O操作,所以也就不能直接访问用户电脑的文件。

但是,也是有办法去访问电脑中的文件,打开文件的。

比如情况一:如果知道电脑文件在什么位置、什么名字。

可以参考这篇文章:
【Unity3D小技巧】Unity3D中打包WEBGL后读取本地文件数据

情况二:知道要上传什么类型的文件,但是需要弹出窗口来选择文件并打开。

这篇文章就来讨论一下WEBGL打开Window文件对话框并打开文件后上传文件,显示图片/文本。

二、实现过程

先来看一下效果:
在这里插入图片描述

2-1、实现分析

既然Unity3D没办法直接进行I/O操作,但是JavaScript可以进行I/O操作,那是不是就可以让Unity跟JS进行通信,来进行操作。

JavaScript打开文件的代码很简单:

<input type="file" /></input>

那么就可以用Unity的按钮去调用这个组件,从这个组件中获取到文件流。

OK,理论存在,实践开始。

2-2、Unity3D中做的准备

(1)在Unity的工程中新建Plugins文件夹:
在这里插入图片描述
(2)在里面新建WebGl.jslib文件,编辑代码,这个文件是JS与WEBGL交互用的。

详情参照Unity官网:https://docs.unity3d.com/Manual/webgl-interactingwithbrowserscripting.html

文件里面的内容如下:

mergeInto(LibraryManager.library, {clickSelectFileBtn:function () {console.log("Enter");clickSelectFileBtn();},
});

(3)搭建Unity程序:
在这里插入图片描述
一个Button用来响应Js函数,一个Image用来显示图片,Text用来显示文本内容。

(3)在Hierarchy视图新建一个Scripts对象(名字需要跟我一样,因为后面要跟js脚本),挂载脚本,脚本名随意:

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Networking;
using UnityEngine.UI;public class ReceiveDataHandle : MonoBehaviour
{public Button BtnLoad;public Image showImg;public Text showText;[DllImport("__Internal")]private static extern void clickSelectFileBtn();/// <summary>/// 点击Open按钮/// </summary>public static void BtnLoadEvent(){clickSelectFileBtn();}void Start(){BtnLoad.onClick.AddListener(BtnLoadEvent);}/// <summary>/// 接收base64字符串/// </summary>/// <param name="base64Str"></param>public void GetBase64(string base64Str){Debug.Log(base64Str);string[] split = base64Str.Split('|');if (split[0].Contains("jpg")){StartCoroutine(ReadTexture(split[1], LoadImg));}else if (split[0].Contains("txt")){StartCoroutine(ReadData(split[1], LoadText));}else{Debug.Log("文件格式错误");return;}}/// <summary>/// 读取图片/// </summary>/// <param name="path"></param>/// <param name="action"></param>/// <returns></returns>IEnumerator ReadTexture(string path,UnityAction<Texture> action){Debug.Log(path);UnityWebRequest request = UnityWebRequestTexture.GetTexture(path);yield return request.SendWebRequest();if (request.isNetworkError || request.isHttpError){Debug.Log(request.error);}else{byte[] imgdata = request.downloadHandler.data;action(DownloadHandlerTexture.GetContent(request));}}/// <summary>/// 加载图片/// </summary>/// <param name="texture"></param>void LoadImg(Texture texture){Sprite ImgSprite = Sprite.Create((Texture2D)texture, new Rect(0, 0, texture.width, texture.height), new Vector2(0.5f, 0.5f));showImg.sprite = ImgSprite;}/// <summary>/// 读取文本/// </summary>/// <param name="path"></param>/// <param name="action"></param>/// <returns></returns>IEnumerator ReadData(string path, UnityAction<string> action){Debug.Log(path);UnityWebRequest request = UnityWebRequest.Get(path);yield return request.SendWebRequest();if (request.isNetworkError || request.isHttpError){Debug.Log(request.error);}else{Debug.Log(request.downloadHandler.text);action(request.downloadHandler.text);}}/// <summary>/// 加载文本/// </summary>/// <param name="text"></param>void LoadText(string text){showText.text = text;}
}

注意:
clickSelectFileBtn函数用来调用Js函数,GetBase64函数用来接收数据。

2-3、打包WEBGL后修改

注意:我用的Unity2019.4.9f1版本。高版本打包出来的index.html以及Build里面的文件跟我的不一致,这个后面有空再说如何匹配高版本吧,先用2019版本演示。

打包之后:
在这里插入图片描述
在这里插入图片描述
修改index.html文件:

<!DOCTYPE html>
<html lang="en-us"><head><meta charset="utf-8"><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><title>Unity WebGL Player | Demo_WEBGLLoadFile</title><link rel="shortcut icon" href="TemplateData/favicon.ico"><link rel="stylesheet" href="TemplateData/style.css"><script src="TemplateData/UnityProgress.js"></script><script src="Build/UnityLoader.js"></script><script>var unityInstance = UnityLoader.instantiate("unityContainer", "Build/WEBGL_LoadFile.json", {onProgress: UnityProgress});function clickSelectFileBtn() {var tempFileLayout = document.getElementById('files');tempFileLayout.click();}function fileImport() {//获取读取我文件的File对象var selectedFile = document.getElementById('files').files[0];if (selectedFile != null) {var reader = new FileReader();reader.readAsDataURL(selectedFile);reader.onload = function (e) {var base64Str = e.currentTarget.result.substring(e.currentTarget.result.indexOf(',') + 1);sendMessageToUnity(base64Str);}}}function sendMessageToUnity(s) {//发送给unityvar file=document.getElementById('files').files[0];SetFileUrlByDragEnd(file);}function SelectFile(){var file=document.getElementById('files').files[0];SetFileUrlByDragEnd(file);}function SetFileUrlByDragEnd(file) {unityInstance.SendMessage("Scripts", "GetBase64", file.name+"|"+URL.createObjectURL(file));}</script></head><body><input type="file" id="files" style="display:none" onchange="fileImport()"><div class="webgl-content"><div id="unityContainer" style="width: 960px; height: 600px"></div><div class="footer"><div class="webgl-logo"></div><div class="fullscreen" onclick="unityInstance.SetFullscreen(1)"></div><div class="title">Demo_WEBGLLoadFile</div></div></div></body>
</html>

代码解释一下:
(1)首先是加了一个<input type="file" id="files" style="display:none" onchange="fileImport()">用来响应打开文件的操作。

(2)然后用Unity程序的Button响应clickSelectFileBtn函数,去触发这个组件。

(3)添加fileImport去处理打开的文件得到文件流。

(4)获得文件名和文件路径,通过unityInstance.SendMessage("Scripts", "GetBase64", file.name+"|"+URL.createObjectURL(file));传给Unity

(5)URL.createObjectURL(file)可以获得本地文件的缓存url,直接发给Unity,然后Unity用来加载。

2-4、效果演示

在这里插入图片描述

三、后记

如果觉得本篇文章有用别忘了点个关注,关注不迷路,持续分享更多Unity干货文章。


你的点赞就是对博主的支持,有问题记得留言:

博主主页有联系方式。

博主还有跟多宝藏文章等待你的发掘哦:

专栏方向简介
Unity3D开发小游戏小游戏开发教程分享一些使用Unity3D引擎开发的小游戏,分享一些制作小游戏的教程。
Unity3D从入门到进阶入门从自学Unity中获取灵感,总结从零开始学习Unity的路线,有C#和Unity的知识。
Unity3D之UGUIUGUIUnity的UI系统UGUI全解析,从UGUI的基础控件开始讲起,然后将UGUI的原理,UGUI的使用全面教学。
Unity3D之读取数据文件读取使用Unity3D读取txt文档、json文档、xml文档、csv文档、Excel文档。
Unity3D之数据集合数据集合数组集合:数组、List、字典、堆栈、链表等数据集合知识分享。
Unity3D之VR/AR(虚拟仿真)开发虚拟仿真总结博主工作常见的虚拟仿真需求进行案例讲解。
Unity3D之插件插件主要分享在Unity开发中用到的一些插件使用方法,插件介绍等
Unity3D之日常开发日常记录主要是博主日常开发中用到的,用到的方法技巧,开发思路,代码分享等
Unity3D之日常BUG日常记录记录在使用Unity3D编辑器开发项目过程中,遇到的BUG和坑,让后来人可以有些参考。
http://www.lryc.cn/news/518697.html

相关文章:

  • C# 或 .NetCore 如何使用 NPOI 导出图片到 Excel 文件
  • Lambda expressions in C++ (C++ 中的 lambda 表达式)
  • 【Rust自学】11.4. 用should_panic检查恐慌
  • 高斯函数Gaussian绘制matlab
  • 获取客户端真实IP地址
  • Kotlin学习(一)
  • 鸿蒙UI开发——日历选择器
  • 2025-1-9 QT 使用 QXlsx库 读取 .xlsx 文件 —— 导入 QXlsx库以及读取 .xlsx 的源码 实践出真知,你我共勉
  • React中createRoot函数原理解读——Element对象与Fiber对象、FiberRootNode与HostRootNode
  • 利用Python实现Union-Find算法
  • 【LeetCode: 912. 排序数组 + 归并排序】
  • AI时代来了,我们不再需要IDE了
  • PL/SQL语言的网络编程
  • vue video重复视频 设置 srcObject 视频流不占用资源 减少资源浪费
  • JavaFx 21 项目Markdown 预览、编辑、新建、文件树、删除、重命名
  • git项目提交步骤(简洁版)
  • 风水算命系统架构与功能分析
  • Clojure语言的学习路线
  • 网络安全核心目标CIA
  • Wi-Fi Direct (P2P)原理及功能介绍
  • Perl语言的数据结构
  • 【MFC】设置CTreeCtrl单个节点的文字颜色
  • 【CSS】设置滚动条样式
  • Gitlab-Runner配置
  • 代码随想录 哈希 test 8
  • [SAP ABAP] 使用LOOP AT...ASSIGNING FIELD-SYMBOL 直接更新内表数据
  • MySQL数据导出导入
  • leetcode 127. 单词接龙
  • 如何开发一个支持海量分布式锁的应用库
  • JavaScript系列(17)--类型系统模拟