Unity构建后EditorUtility.OpenFilePanel报错,求打包可用替代方案
替代Unity EditorUtility.OpenFilePanel的运行时文件选择方案
方案1:Unity官方运行时文件选择API(Windows专属,Unity 2020.1+)
Unity 2020.1及以上版本提供了UnityEngine.Windows.FilePicker类,专门用于Windows平台的运行时文件选择,无需额外依赖,用法示例:
using UnityEngine; using UnityEngine.Windows; public class FilePickerHandler : MonoBehaviour { public void TriggerFilePicker() { // 配置文件筛选规则,格式为「显示名称|*.后缀」,多规则用分号分隔 string[] filters = new string[] { "文本文件|*.txt", "所有格式|*.*" }; FilePicker.ShowOpenFilePanel("选择目标文件", "", filters, false, (string[] selectedPaths) => { if (selectedPaths != null && selectedPaths.Length > 0) { Debug.Log("选中文件路径:" + selectedPaths[0]); // 这里添加文件选中后的处理逻辑 } }); } }
方案2:跨平台原生API调用
如果需要支持Windows、macOS、Linux多平台,可以通过平台编译宏分别调用各系统的原生文件对话框:
Windows平台(基于System.Windows.Forms)
需要先在Unity编辑器中把项目API兼容级别设置为**.NET Framework**(路径:Edit > Project Settings > Player > Other Settings > Configuration),然后添加对System.Windows.Forms.dll的引用,代码示例:
#if UNITY_STANDALONE_WIN using System.Windows.Forms; public void OpenWinFileDialog() { OpenFileDialog fileDialog = new OpenFileDialog(); fileDialog.Filter = "文本文件|*.txt|所有格式|*.*"; fileDialog.Title = "选择文件"; if (fileDialog.ShowDialog() == DialogResult.OK) { string targetPath = fileDialog.FileName; Debug.Log("选中文件路径:" + targetPath); } } #endif
macOS平台(调用Objective-C原生API)
通过DllImport调用macOS的NSOpenPanel:
#if UNITY_STANDALONE_OSX using System.Runtime.InteropServices; public static class MacFileSelector { [DllImport("__Internal")] private static extern string ShowMacOpenDialog(string fileFilter); public static string GetSelectedFile(string filter = "txt") { return ShowMacOpenDialog(filter); } } // 使用示例 public void TriggerMacFilePicker() { string selectedPath = MacFileSelector.GetSelectedFile("txt"); if (!string.IsNullOrEmpty(selectedPath)) { Debug.Log("选中文件路径:" + selectedPath); } }
同时需要在项目Plugins/macOS目录下添加一个Objective-C文件(命名为MacFileDialog.m),内容如下:
#include <Cocoa/Cocoa.h> const char* ShowMacOpenDialog(const char* filter) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NSOpenPanel* openPanel = [NSOpenPanel openPanel]; [openPanel setCanChooseFiles:YES]; [openPanel setCanChooseDirectories:NO]; [openPanel setAllowedFileTypes:@[ [NSString stringWithUTF8String:filter] ]]; NSString* resultPath = nil; if ([openPanel runModal] == NSModalResponseOK) { resultPath = [[openPanel URL] path]; } const char* pathCStr = [resultPath UTF8String]; char* copiedPath = pathCStr ? strdup(pathCStr) : NULL; [pool release]; return copiedPath; }
Linux平台(调用GTK API)
通过DllImport调用GTK的文件选择对话框:
#if UNITY_STANDALONE_LINUX using System.Runtime.InteropServices; public static class LinuxFileSelector { [DllImport("libgtk-3.so.0")] private static extern IntPtr gtk_file_chooser_dialog_new(string title, IntPtr parent, int action, string btn1, int resp1, string btn2, int resp2, IntPtr end); [DllImport("libgtk-3.so.0")] private static extern void gtk_widget_show_all(IntPtr dialog); [DllImport("libgtk-3.so.0")] private static extern int gtk_dialog_run(IntPtr dialog); [DllImport("libgtk-3.so.0")] private static extern IntPtr gtk_file_chooser_get_filename(IntPtr dialog); [DllImport("libglib-2.0.so.0")] private static extern void g_free(IntPtr ptr); [DllImport("libgtk-3.so.0")] private static extern void gtk_widget_destroy(IntPtr dialog); private const int GTK_FILE_CHOOSER_ACTION_OPEN = 0; private const int GTK_RESPONSE_OK = -5; public static string GetSelectedFile() { IntPtr dialog = gtk_file_chooser_dialog_new("选择文件", IntPtr.Zero, GTK_FILE_CHOOSER_ACTION_OPEN, "取消", -6, "打开", GTK_RESPONSE_OK, IntPtr.Zero); gtk_widget_show_all(dialog); string resultPath = null; if (gtk_dialog_run(dialog) == GTK_RESPONSE_OK) { IntPtr filenamePtr = gtk_file_chooser_get_filename(dialog); resultPath = System.Runtime.InteropServices.Marshal.PtrToStringAnsi(filenamePtr); g_free(filenamePtr); } gtk_widget_destroy(dialog); return resultPath; } } // 使用示例 public void TriggerLinuxFilePicker() { string selectedPath = LinuxFileSelector.GetSelectedFile(); if (!string.IsNullOrEmpty(selectedPath)) { Debug.Log("选中文件路径:" + selectedPath); } } #endif
方案3:第三方插件
如果不想自行编写跨平台原生代码,可以使用成熟的第三方文件选择插件,这类插件通常已封装好各平台的原生实现,直接调用统一API即可完成文件选择功能。
注意事项
- 使用
System.Windows.Forms时,必须确保项目API兼容级别设置为**.NET Framework**,否则会出现编译错误。 - 各平台的原生代码需放在对应平台的
Plugins子目录下,Unity会自动根据打包平台筛选加载对应的代码。
内容的提问来源于stack exchange,提问作者Miguel
相关产品推荐
相关产品推荐

