我希望用户在Unity WebGL游戏中从计算机中选择一个图像,但我无法获得任何库或代码.我想要UnityWebGL(Runtime)的EditorUtility.OpenFilePanel的确切功能.
string path = EditorUtility.OpenFilePanel("用png覆盖","","png");
有没有办法在Unity WebGL构建中获得这个打开的对话框?或者我有什么方法可以在java脚本中做到这一点?就像我从用户的java脚本中获取图像并将其传递给我的C#代码.
这可能听起来很简单,但实际上它很复杂,原因是WebGL构建在浏览器中运行,并受到许多安全限制,其中包括限制其对本地文件系统的访问.但是,有可能以一种黑客的方式做到这一点.
想法是使用HTML文件输入来打开文件浏览对话框.我们可以使用ExternalEval从Unity代码中调用它,详情请见:http : //docs.unity3d.com/Manual/UnityWebPlayerandbrowsercommunication.html http://docs.unity3d.com/ScriptReference/Application.ExternalEval.html
然而,事情并非那么容易.问题是所有现代浏览器都允许仅作为用户点击事件的结果显示文件对话框,作为安全限制,您无法对其进行任何操作.
好的,所以我们可以创建一个按钮,并在点击时打开文件对话框,这样可行,对吗?错误.如果我们只是创建统一按钮并处理单击 - 这将无法工作,因为Unity有自己的事件管理,它与帧速率同步,因此事件将仅在实际的javascript事件结束时发生.这几乎和这里描述的问题一样,http://docs.unity3d.com/Manual/webgl-cursorfullscreen.html除了Unity没有很好的内置解决方案.
所以这是黑客攻击:点击鼠标按下+鼠标向上,对吧?我们将点击监听器添加到HTML文档中,然后在统一中我们按下鼠标按下我们的按钮.当它关闭时,我们知道下一个UP将被点击,所以我们在HTML文档中标记一些标记以记住它.然后,当我们点击文档时,我们可以查看此标志并结束我们的按钮被点击.然后我们调用打开文件对话框的javascript函数,然后使用SendMessage http://docs.unity3d.com/Manual/webgl-interactingwithbrowserscripting.html将结果发送回Unity .最后.
但等等,还有更多.问题是我们不能简单地在浏览器中运行时获取文件路径.我们的应用程序不允许再获取有关用户计算机的任何信息,安全限制.我们能做的最好的事情是使用URL.CreateObjectURL获取一个blob url,它可以在大多数浏览器上运行,http: //caniuse.com/#search=createobjecturl
我们可以使用WWW类从中检索数据,只需记住此URL只能在您的应用程序范围内访问.
所有这些,解决方案非常hacky,但可能.这是一个示例代码,允许用户选择图像,并将其设置为材质.
using UnityEngine; using UnityEngine.UI; using UnityEngine.EventSystems; using System.Collections; public class OpenFileDialog : MonoBehaviour, IPointerDownHandler { public Renderer preview; public Text text; void Start() { Application.ExternalEval( @" document.addEventListener('click', function() { var fileuploader = document.getElementById('fileuploader'); if (!fileuploader) { fileuploader = document.createElement('input'); fileuploader.setAttribute('style','display:none;'); fileuploader.setAttribute('type', 'file'); fileuploader.setAttribute('id', 'fileuploader'); fileuploader.setAttribute('class', 'focused'); document.getElementsByTagName('body')[0].appendChild(fileuploader); fileuploader.onchange = function(e) { var files = e.target.files; for (var i = 0, f; f = files[i]; i++) { window.alert(URL.createObjectURL(f)); SendMessage('" + gameObject.name +@"', 'FileDialogResult', URL.createObjectURL(f)); } }; } if (fileuploader.getAttribute('class') == 'focused') { fileuploader.setAttribute('class', ''); fileuploader.click(); } }); "); } public void OnPointerDown (PointerEventData eventData) { Application.ExternalEval( @" var fileuploader = document.getElementById('fileuploader'); if (fileuploader) { fileuploader.setAttribute('class', 'focused'); } "); } public void FileDialogResult(string fileUrl) { Debug.Log(fileUrl); text.text = fileUrl; StartCoroutine(PreviewCoroutine(fileUrl)); } IEnumerator PreviewCoroutine(string url) { var www = new WWW(url); yield return www; preview.material.mainTexture = www.texture; } }
如果有人设法找到一种更简单的方法请分享,但我真的怀疑它是否有可能.希望这可以帮助.