如何在Unity(C#)中打开Windows资源管理器的文件选择模式以实现图片导入
嘿,我完全懂你现在的需求——在Unity里做一款资源制作工具,点击按钮让用户通过系统文件选择器挑图片,再把图片复制到项目Assets/Resources下的指定文件夹对吧?你之前尝试用Process调用explorer.exe的思路其实走偏了,因为资源管理器本身不是为文件选择交互设计的,没法返回用户选中的文件路径。咱们换用更合适的API来实现,分两种场景给你方案:
方案1:编辑器专用工具(推荐,适配你的开发场景)
如果你的工具只在Unity编辑器里运行(不需要打包成独立程序),直接用Unity内置的编辑器API就够了,简单还靠谱。
首先把脚本放在项目的Editor文件夹下(因为编辑器API只能在这个目录的脚本里生效),然后写如下代码:
using UnityEditor; using UnityEngine; using System.IO; public class ImageImporterTool : EditorWindow { // 给Unity顶部菜单栏加一个入口 [MenuItem("Tools/Image Importer/Open Selector")] public static void LaunchTool() { GetWindow<ImageImporterTool>("Image Importer"); } private void OnGUI() { if (GUILayout.Button("Select & Import Image", GUILayout.Height(40))) { // 弹出系统原生文件选择框,只允许选择图片格式 string selectedFilePath = EditorUtility.OpenFilePanel( "Pick an Image File", "", // 默认打开路径为空,会记住上次打开的位置 "png,jpg,jpeg,bmp,tga" ); // 用户点击取消的话,路径会是空字符串,直接跳过 if (string.IsNullOrEmpty(selectedFilePath)) return; // 定义目标文件夹路径:Assets/Resources/ImportedImages(你可以改成自己的文件夹名) string targetFolder = Path.Combine(Application.dataPath, "Resources/ImportedImages"); // 如果目标文件夹不存在,自动创建 if (!Directory.Exists(targetFolder)) { Directory.CreateDirectory(targetFolder); } // 提取选中文件的文件名,拼接目标完整路径 string fileName = Path.GetFileName(selectedFilePath); string targetFilePath = Path.Combine(targetFolder, fileName); try { // 复制文件,允许覆盖同名文件 File.Copy(selectedFilePath, targetFilePath, overwrite: true); Debug.Log($"✅ 图片导入成功:{targetFilePath}"); // 刷新Unity资源数据库,让新复制的文件立刻在Project窗口显示 AssetDatabase.Refresh(); } catch (System.Exception e) { Debug.LogError($"❌ 导入失败:{e.Message}"); } } } }
关键点说明:
EditorUtility.OpenFilePanel是Unity专门为编辑器提供的文件选择API,直接弹出系统原生对话框,还能过滤文件格式,比调用资源管理器可控多了- 复制完成后必须调用
AssetDatabase.Refresh(),不然Unity不会立刻识别到新文件 - 用
Application.dataPath拼接路径,能保证拿到的是项目Assets文件夹的绝对路径,不会出错
方案2:支持打包成独立程序(如果你的工具需要分发)
要是你需要把工具打包成独立Windows程序运行,就不能用编辑器API了,得用.NET的OpenFileDialog:
- 先去Unity的
Player Settings里,把API Compatibility Level改成.NET Framework(默认的.NET Standard不支持System.Windows.Forms) - 然后写如下脚本:
using UnityEngine; using System.IO; using System.Windows.Forms; public class StandaloneImageImporter : MonoBehaviour { // 给UI按钮绑定这个方法 public void OnSelectImageClicked() { OpenFileDialog fileDialog = new OpenFileDialog(); fileDialog.Filter = "Image Files|*.png;*.jpg;*.jpeg;*.bmp;*.tga"; fileDialog.Title = "Select an Image to Import"; if (fileDialog.ShowDialog() == DialogResult.OK) { string selectedPath = fileDialog.FileName; // 打包后注意:Resources文件夹会被整合进程序,所以如果是工具输出,建议用StreamingAssets或者可读写目录 string targetFolder = Path.Combine(Application.streamingAssetsPath, "ImportedImages"); if (!Directory.Exists(targetFolder)) { Directory.CreateDirectory(targetFolder); } string fileName = Path.GetFileName(selectedPath); string targetPath = Path.Combine(targetFolder, fileName); try { File.Copy(selectedPath, targetPath, overwrite: true); Debug.Log($"✅ 图片已复制到:{targetPath}"); } catch (System.Exception e) { Debug.LogError($"❌ 复制失败:{e.Message}"); } } } }
注意事项:
- 打包时Unity通常会自动处理
System.Windows.Forms.dll的依赖,要是遇到问题,可以手动从你的.NET Framework目录(比如C:\Windows\Microsoft.NET\Framework64\v4.0.30319\System.Windows.Forms.dll)把dll复制到项目的Plugins文件夹里 - 打包后
Resources文件夹是只读的,所以如果是工具输出文件,建议用StreamingAssets或者Application.persistentDataPath这类可读写目录
为什么你之前的方法行不通?
你调用explorer.exe的方式只能打开资源管理器窗口,但没办法获取用户选中的文件路径——资源管理器没有提供返回选中文件的机制,它适合打开指定文件夹,但完全不适合做文件选择交互。咱们需要用专门的文件选择对话框API,才能拿到用户的选择结果,进而完成后续的复制操作。
内容的提问来源于stack exchange,提问作者SpicyMelon




