You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在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

  1. 先去Unity的Player Settings里,把API Compatibility Level改成.NET Framework(默认的.NET Standard不支持System.Windows.Forms
  2. 然后写如下脚本:
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

火山引擎 最新活动