使用unity自带API EditorUtility打开本地文件夹或者文件,以及打包后发布打开本地文件夹

本文介绍如何在Unity中实现文件与文件夹的操作,包括使用内置编辑器工具及跨平台的文件对话框实现,提供了具体的C#代码示例。

首先我们查一下unity官方手册可以看到下面的画面(我是使用谷歌浏览器的翻译)。

我们点进打开文件OpenFilePanel里去看官方示例,代码如下:

using System.IO;
using UnityEngine;
using UnityEditor;

public class OpenFilePanelExample : EditorWindow
{
    [MenuItem("Example/Overwrite Texture")]
    static void Apply()
    {
        Texture2D texture = Selection.activeObject as Texture2D;
        if (texture == null)
        {
            EditorUtility.DisplayDialog("Select Texture", "You must select a texture first!", "OK");
            return;
        }

        string path = EditorUtility.OpenFilePanel("Overwrite with png", "", "png");
        if (path.Length != 0)
        {
            var fileContent = File.ReadAllBytes(path);
            texture.LoadImage(fileContent);
        }
    }
}

再看一下打开文件夹OpenFolderPanel官方示例,代码如下:

using UnityEditor;
using System.IO;

public class OpenFolderPanelExample : EditorWindow
{
    [MenuItem("Example/Load Textures To Folder")]
    static void Apply()
    {
        string path = EditorUtility.OpenFolderPanel("Load png Textures", "", "");
        string[] files = Directory.GetFiles(path);

        foreach (string file in files)
            if (file.EndsWith(".png"))
                File.Copy(file, EditorApplication.currentScene);
    }
}

 

是不是觉得大同小异呢,SaveFilePanel以及SaveFolderPanel也是同样的方式我这里就不演示。

我的应用代码如下:


    void ConfirmBtnClick()
    {
        
        //SceneManager.LoadScene(1);
        string AssetsPath = Application.dataPath + "/Resources/";
        string Path = EditorUtility.SaveFolderPanel("请选择文件夹", AssetsPath, "");
        if (Path.Length != 0)
        {
            Debug.Log("开始保存数据");
            ///TODO  保存数据

            SceneManager.LoadScene(1);
        }
        else
        {
            Debug.Log("取消保存");
        }
        
    }

因为接下来需要保存的数据还没有完成,所以这里只是debug一下。

上面的方法虽然在Unity编辑器里是可以打开文件夹的,但是我们将软件打包是会发现报错无法打包,这是因为该脚本引用using UnityEditor;只能在编辑器下使用,所以我们还是不要想着偷懒老老实实使用类吧,首先我们创建两个类。

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public class OpenFileName
{
    public int structSize = 0;
    public IntPtr dlgOwner = IntPtr.Zero;
    public IntPtr instance = IntPtr.Zero;
    public String filter = null;
    public String customFilter = null;
    public int maxCustFilter = 0;
    public int filterIndex = 0;
    public String file = null;
    public int maxFile = 0;
    public String fileTitle = null;
    public int maxFileTitle = 0;
    public String initialDir = null;
    public String title = null;
    public int flags = 0;
    public short fileOffset = 0;
    public short fileExtension = 0;
    public String defExt = null;
    public IntPtr custData = IntPtr.Zero;
    public IntPtr hook = IntPtr.Zero;
    public String templateName = null;
    public IntPtr reservedPtr = IntPtr.Zero;
    public int reservedInt = 0;
    public int flagsEx = 0;
}

以及

public class LocalDialog
{
    //链接指定系统函数       打开文件对话框
    [DllImport("Comdlg32.dll", SetLastError = true, ThrowOnUnmappableChar = true, CharSet = CharSet.Auto)]
    public static extern bool GetOpenFileName([In, Out] OpenFileName ofn);
    public static bool GetOFN([In, Out] OpenFileName ofn)
    {
        return GetOpenFileName(ofn);
    }

    //链接指定系统函数        另存为对话框
    [DllImport("Comdlg32.dll", SetLastError = true, ThrowOnUnmappableChar = true, CharSet = CharSet.Auto)]
    public static extern bool GetSaveFileName([In, Out] OpenFileName ofn);
    public static bool GetSFN([In, Out] OpenFileName ofn)
    {
        return GetSaveFileName(ofn);
    }
}

接下来直接调用就可以了

 /// <summary>
    /// 打开windows保存窗口
    /// </summary>
    /// <returns>路径名(带名字)</returns>
    string loadFile()
    {
        OpenFileName openFileName = new OpenFileName();
        openFileName.structSize = Marshal.SizeOf(openFileName);
        openFileName.filter = "All files (*.*)|*.*";
        openFileName.file = new string(new char[256]);
        openFileName.maxFile = openFileName.file.Length;
        openFileName.fileTitle = new string(new char[64]);
        openFileName.maxFileTitle = openFileName.fileTitle.Length;
        openFileName.initialDir = Application.streamingAssetsPath.Replace('/', '\\');//默认路径
        openFileName.title = "保存项目";
        openFileName.flags = 0x00080000 | 0x00001000 | 0x00000800 | 0x00000008;

        if (LocalDialog.GetSaveFileName(openFileName))
        {
            return openFileName.file;

        }
        else
        {
            return null;
        }


    }

因为我需要获取返回的路径名使用,所以我将它写成带返回值的函数。我们实际调用一下试试

/// <summary>
    /// 确定保存
    /// </summary>
    void ConfirmBtnClick()
    {

        //SceneManager.LoadScene(1);
        //string AssetsPath = Application.dataPath + "/Resources/";
        //string Path = UnityEditor.EditorUtility.SaveFolderPanel("请选择文件夹", AssetsPath, "");
        string Path=loadFile();
        if (Path != null)
        {
            if (Path.Length != 0)
            {
                Debug.Log("开始保存数据");
                
            }
        }
        
        else
        {
            Debug.Log("取消保存");
        }
        
    }

具体代码就这样

<think>好的,我现在需要回答用户关于如何在Windows端的Unity打开本地文件夹并获取文件路径的问题。用户之前已经询问过Unity读取Office文件的方法,现在可能是在继续开发相关功能,需要让用户选择文件。 首先,我需要回想Unity中处理文件对话框的方法。Unity本身没有内置的文件浏览器,所以通常需要调用系统原生对话框。对于Windows平台,可以使用COM组件Windows API,但这样可能不够跨平台。或者使用第三方库插件。 用户可能想要的是在Unity编辑器Windows独立游戏中实现这个功能。如果是编辑器扩展,可以使用UnityEditor命名空间中的EditorUtility.OpenFilePanel。如果是运行时,比如游戏构建后,可能需要不同的方法,比如使用System.Windows.Forms的OpenFileDialog,但这需要配置DLL和兼容性设置。 然后,我需要考虑跨平台问题。如果用户只关注Windows端,可以专注于Windows的解决方案。但如果是多平台,可能需要更通用的方法,比如使用Unity的Application.streamingAssetsPath其他路径,但这可能不涉及用户交互选择文件。 接下来,要确保提供的代码示例正确。比如,使用EditorUtility在编辑器下有效,但在构建后不可用,所以需要区分编辑器模式和运行时。对于运行时,可能需要引入System.Windows.Forms,这需要将相关DLL放入Plugins文件夹,并处理单线程问题,因为Unity在主线程运行,而Windows窗体可能需要消息循环。 另外,用户可能需要获取文件的完整路径,或者只是读取文件内容。根据之前的对话,用户可能更关注路径获取,以便后续处理文件,如读取Word、Excel等。 还要注意权限问题,特别是在较新版本的Windows中,可能需要检查应用是否有权限访问指定目录。此外,路径中的反斜杠可能需要转换为Unity可识别的格式,比如使用Path.Combine替换为正斜杠。 最后,总结步骤:判断是否在编辑器下,使用不同的方法;处理DLL依赖;提供代码示例并说明注意事项,如平台限制、线程问题等。同时,推荐使用资产商店的插件简化流程,如果用户需要更稳定的解决方案。</think>在Unity中实现 **Windows端本地文件夹/文件选择** 并获取路径信息,可以通过以下两种主要方法实现: -- ### **1. 使用Unity编辑器API(仅限编辑器模式)** 适用于开发阶段在Unity Editor中快速测试文件选择功能,**但无法在打包后的EXE程序中运行**。 ```csharp using UnityEditor; // 需要引入命名空间 public class FileBrowserExample : MonoBehaviour { // 打开文件选择对话框 public void OpenFile() { string path = EditorUtility.OpenFilePanel("选择文件", "", "docx,ppt,xlsx,txt"); if (!string.IsNullOrEmpty(path)) { Debug.Log("选中文件路径: " + path); // 读取文件内容(示例) byte[] bytes = File.ReadAllBytes(path); } } // 打开文件夹选择对话框 public void OpenFolder() { string path = EditorUtility.OpenFolderPanel("选择文件夹", "", ""); if (!string.IsNullOrEmpty(path)) { Debug.Log("选中文件夹路径: " + path); // 遍历文件夹文件 string[] files = Directory.GetFiles(path); } } } ``` -- ### **2. 使用Windows原生API(适用于打包后的EXE程序)** 通过调用Windows系统的`System.Windows.Forms`实现,需配置以下步骤: #### **步骤1:添加DLL依赖** - 在Unity项目根目录创建 `Plugins` 文件夹。 - 从Windows系统中复制以下DLL文件到Plugins目录: - `System.Windows.Forms.dll` - `System.Drawing.dll` - `Accessibility.dll` #### **步骤2:编写文件选择代码** ```csharp using System.Windows.Forms; // 需要引入命名空间 using UnityEngine; public class NativeFileBrowser : MonoBehaviour { // 打开文件对话框 public void OpenFileDialog() { OpenFileDialog dialog = new OpenFileDialog(); dialog.Title = "选择文件"; dialog.Filter = "Office文件|*.docx;*.xlsx;*.pptx|所有文件|*.*"; if (dialog.ShowDialog() == DialogResult.OK) { string path = dialog.FileName; Debug.Log("文件路径: " + path); // 示例:读取文件内容 string textContent = File.ReadAllText(path); } } // 打开文件夹对话框 public void OpenFolderDialog() { FolderBrowserDialog dialog = new FolderBrowserDialog(); dialog.Description = "选择文件夹"; if (dialog.ShowDialog() == DialogResult.OK) { string path = dialog.SelectedPath; Debug.Log("文件夹路径: " + path); // 示例:获取文件夹内所有文件 string[] files = Directory.GetFiles(path); } } } ``` --- ### **3. 跨平台兼容性处理** 若需要同时支持编辑器模式和打包后的程序,可使用条件编译: ```csharp public class UniversalFileBrowser : MonoBehaviour { public void OpenFile() { #if UNITY_EDITOR string path = EditorUtility.OpenFilePanel("选择文件", "", "*"); #else OpenFileDialog dialog = new OpenFileDialog(); if (dialog.ShowDialog() != DialogResult.OK) return; string path = dialog.FileName; #endif Debug.Log("最终路径: " + path); } } ``` -- ### **4. 注意事项** 1. **线程问题** Windows窗体对话框可能阻塞Unity主线程,建议在协程中异步调用: ```csharp IEnumerator OpenFileAsync() { var dialog = new OpenFileDialog(); yield return new WaitUntil(() => dialog.ShowDialog() == DialogResult.OK); Debug.Log("路径: " + dialog.FileName); } ``` 2. **路径格式转换** Windows路径使用反斜杠`\`,Unity中需替换为正斜杠`/`: ```csharp string unityPath = path.Replace("\\", "/"); ``` 3. **权限问题** 打包后的程序可能需要管理员权限才能访问某些系统目录。 --- ### **5. 替代方案:使用第三方插件** - **SimpleFileBrowser (Asset Store免费插件)** 提供跨平台支持,无需处理DLL依赖。 ![SimpleFileBrowser插件示例](https://assetstorev1.prd.unity3d.com/public/images/assetbar_small.png) - **NativeFilePicker (开源库)** GitHub地址:https://github.com/yasirkula/UnityNativeFilePicker --- ### **总结** - **编辑器调试**:优先使用`EditorUtility`快速验证逻辑。 - **打包后程序**:通过Windows原生API第三方插件实现。 - **跨平台需求**:推荐使用SimpleFileBrowser等插件简化开发。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值