Unity WebPlayer下打开、另存为本地文件浏览器,更改颜色等等
说到本地文件操作,可能最常用的一种方式是导入System.Windows.Forms.dll,即调用Winfor的窗体函数,完成打开或者另存为修改本地文件的操作,但是当在PC平台下编译的时候,我们就必须把Other Settings里面的Api Compatibility Level设置成为.NET 2.0,至于这个选项的意义,圣典里说的很清楚,.Net 2.0 库是最大.net 兼容性, 最大文件大小,而 .Net 2.0 Subset则是完整的子集 .net 兼容性,较小的文件大小,熟悉Unity WebPlayer环境的开发者都知道,在Web平台下,该选项变灰了,即只能选择Webplayer Subset,这是因为Unity webplayer是一种沙箱操作,是安全性很高的一种操作,它本身是不允许用户操作本地数据的,同时也不允许用户自己开进程。为了实现在Web平台下操作本地的文件,走了不少弯路,现在整理出来,算是总结吧。
弯路1. 误以为是因为自己导入的System.Windows.Forms.dll版本太高的问题,于是多方搜集了3.5版本的,甚至2.0版本的,可是不管哪个版本,都无法在Webplayer subset下编译通过,后来仔细阅读了.NET 2.0与.Net 2.0 Subset的区别,发现这个想法不对,Pass;
弯路2. 将System.Windows.Forms.dll定义成自定义dll
在VS下新建了个类库项目,引用了System.Windows.Forms.dll,利用这个引用写了几个操作接口,然后编译,编译属性选择了.Net framework3.5而不是4.0,这样将编译出来的dll导入Unity没问题,但是打包的时候出错了,提示该自定义dll引用了外部dll,而该dll不可用或者找不到,绕了一圈还是回到了老问题,看来这种方法不可用,Pass;
弯路3. 直接打开快捷方式
Unity可以直接打开绝对路径或者相对路径下的快捷方式,即Application.OpenURL("XX");,于是我将桌面的快捷方式以相对路径的方式在Unity下打开,这种方法虽然可以看到本机的目录结构,但是当选择某个文件的时候便成了直接下载,于是Pass掉这种方法;
弯路4. 让Unity打开exe
在VS下很容易就能实现打开、另存为本地文件浏览的功能,于是新建了Winform窗体应用程序,将编译好的exe放到了Unity项目下面,接着要做的便是调用该exe了,最常用的方法自然是这个了:Process.Start("C://Windows/System32/cmd.exe");,但是打包的时候依然报错,同样的错误,原来是沙箱环境中不允许用户自己开进程,Pass掉这种方法;
弯路5. 让Unity运行二进制文件以打开外部程序
其实上一种方法跟这种方法一样,只是当时自己误以为这种方式也许会行得通,非得等到碰壁了才回头,原理不多讲了,就是自己写了个bat,bat的内容是运行外部的exe,于是这种方法也以失败告终,Pass;
弯路6. exeCommand
document.execCommand('SaveAs','mycodes.txt');
只是IE支持,而且不能自定义保存内容,默认的是该html页面;
方案7. Unity调用js函数,js将用户选择回调给Unity
试了一圈,终于把方案定位到利用JS,但是这种方案又分两种解决办法,但是都不太理想。
方法一:手动创建Html结点,利用Html实现本地文件的浏览,以下是示例代码:
Unity中:
public void OpenFile()
{
Application.ExternalCall ("OpenFile", "UIRoot");
}
JS中:此处的js是打包生成的XX.html中的函数
<script type = "text/javascript" language = "javascript">
function OpenFile(arg)
{
if(document.getElementById('OpenFile') == null)
{
var div = document.createElement("div");
var parent = document.getElementById('content');
div.id = "OpenFile";
div.innerHTML = "<input type=\"file\" name=\"fileField\" class=\"file\" id=\"fileField\" size=\"28\" onchange=\"OnChanged(this)\" />";
parent.insertBefore(div, parent.childNodes[0]);
}
}
<script>
当用户选择了某文件的时候,调用OnChanged函数
function OnChanged(myFiles)
{
document.getElementById('content').removeChild(document.getElementById('OpenFile'));//删除掉刚才创建的结点
u.getUnity().SendMessage("Cube", "GetData", myFiles);//传回Unity
}
上面这个函数的位置需要注意下,因为用到了u这个变量,所以必须把这个函数加到var u = new UnityObject2(config);这个函数体里面,如果大家有研究过Unity webplayer编译出来的html的话,这个也就不难理解了,效果如下图:
前端比较厉害的还可以给这个新建的结点加些样式什么的,打开的效果就跟最常用的上传文件没什么区别:
而如果我们要操作颜色选择器的话,也是类似,只需要将input type改为color就可以了,效果如下:
这种方法貌似粗陋地实现了所需要的功能,但是“另存为”却成了不可逾越的一个坎,试了很多办法,都不能很好地实现另存为的功能,于是在一次一次地尝试中,就有了第二种办法,也就是ActiveXObject,可惜遗憾的是,ActiveXObject只能被IE支持,而且需要配置IE的安全选项,不管怎么说,也是种方法,所以先将浏览器的兼容性抛一边吧,因为本身在Web操作本地文件读写就已经是不合理的了。
方法二:
Unity端不变,JS端代码如下:
function SaveFile(arg)
{
var fd = new ActiveXObject("MSComDlg.CommonDialog");
fd.Filter = "Text Files (*.txt)|*.txt";
fd.FilterIndex = 2;
fd.MaxFileSize = 128;
fd.ShowSave();//此处ActiveXObject提供了ShowColor、ShowOpen等函数,还有其他的操作,这里就不细说了
if(fd.filename=="" || fd.filename.length<1)
{
return false;
}
else
{
//你的操作,或者传回Unity
}
}
效果如下:
到此,差不多可以实现功能了,只是只能在IE下运行,我想,肯定还会有别的办法,以后不断探索吧~~