如何在C#中将Unity项目打包进最终.exe并隐藏?
解决方案:将Unity构建产物嵌入并隐藏到自定义C# EXE中
核心思路
Unity构建产物(主EXE及_Data文件夹)无法直接合并到你的C# EXE中,因为Unity运行时依赖磁盘上的固定文件结构。最可行的方案是将Unity资源嵌入为C#项目的嵌入资源,程序运行时动态提取到临时目录启动,退出后自动清理痕迹。
方案一:嵌入资源+临时目录提取启动
这是最稳定的实现方式,步骤如下:
将Unity构建文件添加为嵌入资源
- 把Unity构建生成的所有文件(主EXE、_Data文件夹及其子文件)复制到你的C#项目目录下
- 选中所有文件,右键→属性→设置生成操作为「嵌入的资源」
- 注意:若资源层级较深,需确保资源名称能映射到正确的路径(可在项目文件中调整资源的
LogicalName)
编写提取与启动代码
在C#程序入口中添加以下逻辑:using System; using System.IO; using System.Reflection; using System.Diagnostics; class Program { static void Main(string[] args) { // 创建唯一临时目录,避免多实例冲突 string tempDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); Directory.CreateDirectory(tempDir); try { Assembly currentAssembly = Assembly.GetExecutingAssembly(); // 遍历所有嵌入资源并提取到临时目录 foreach (string resourceName in currentAssembly.GetManifestResourceNames()) { // 移除命名空间前缀,还原原文件路径 string relativePath = resourceName.Replace($"{currentAssembly.GetName().Name}.", ""); string targetPath = Path.Combine(tempDir, relativePath); // 创建目标文件的父目录 Directory.CreateDirectory(Path.GetDirectoryName(targetPath)); // 将嵌入资源写入磁盘 using (Stream resourceStream = currentAssembly.GetManifestResourceStream(resourceName)) using (FileStream fileStream = new FileStream(targetPath, FileMode.Create)) { resourceStream.CopyTo(fileStream); } } // 启动Unity构建的EXE(替换为你的Unity主EXE文件名) ProcessStartInfo startInfo = new ProcessStartInfo { FileName = Path.Combine(tempDir, "UnityGame.exe"), WorkingDirectory = tempDir // 必须设置工作目录,否则Unity找不到_Data文件夹 }; Process unityProcess = Process.Start(startInfo); unityProcess.WaitForExit(); // 等待Unity进程结束 } finally { // 无论是否异常,都清理临时目录 if (Directory.Exists(tempDir)) { Directory.Delete(tempDir, true); } } } }关键注意事项
- 必须设置Unity进程的
WorkingDirectory为临时目录,否则Unity无法加载_Data文件夹 - 嵌入资源的名称需正确映射到原文件路径,避免提取后结构混乱
- 若Unity程序可能后台运行,需通过进程ID跟踪确保正确检测进程结束
- 必须设置Unity进程的
方案二:Unity单文件构建简化嵌入
如果你的Unity版本在2021.2及以上,可使用Unity的单文件构建功能:
- 在Unity发布设置中,勾选「单文件构建」(Windows平台),生成一个独立的EXE文件(无需_Data文件夹)
- 将这个单EXE嵌入到C#项目中,提取到临时目录启动即可,逻辑比方案一更简洁
额外隐藏优化
- 可将临时目录创建在用户目录的隐藏文件夹下(如
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), ".HiddenGame")),但本质仍需提取到磁盘,无法完全避免运行时文件存在 - 无需额外加密资源,加密后运行时仍需解密到磁盘,反而增加性能开销和复杂度
内容的提问来源于stack exchange,提问作者GiveUpOxygene
相关产品推荐
相关产品推荐

