如何将集成Python脚本的Unity应用打包为单个可执行文件?
如何将集成Python脚本的Unity应用打包为单个可执行文件?
我来给你几个实用的方案,都是开发者们实际验证过的,能帮你把Unity和Python脚本打包成一个单独的可执行文件,不用手动分开启动两者:
方案一:将Python脚本打包为EXE,让Unity自动启动它
这是最常用的方案,上手简单,对原有socket通信逻辑改动最小:
- 第一步:用PyInstaller把你的Python脚本打包成单文件EXE。打开终端,进入Python脚本所在目录,运行命令:
pyinstaller --onefile your_script.py。如果脚本依赖第三方库,记得加上--hidden-import 库名参数把缺失的库打包进去,比如pyinstaller --onefile --hidden-import socket your_script.py。 - 第二步:把打包好的Python EXE放到Unity项目的
StreamingAssets文件夹里(如果没有这个文件夹就新建一个)。 - 第三步:在Unity里写一个C#脚本,在应用启动时自动启动这个Python EXE,同时处理socket连接。示例代码大概是这样的:
using System.Diagnostics; using UnityEngine; using System.IO; public class PythonStarter : MonoBehaviour { void Start() { string pythonExePath = Path.Combine(Application.streamingAssetsPath, "your_script.exe"); ProcessStartInfo startInfo = new ProcessStartInfo(pythonExePath); // 隐藏Python的控制台窗口,避免弹出黑框 startInfo.WindowStyle = ProcessWindowStyle.Hidden; Process.Start(startInfo); // 这里接着写你的socket连接逻辑,记得加一点延迟,确保Python服务已经启动 Invoke("ConnectToPython", 2f); } void ConnectToPython() { // 你的Unity socket客户端代码,比如初始化Socket并连接到localhost的指定端口 } // 应用退出时关闭Python进程,避免残留僵尸进程 void OnApplicationQuit() { foreach (Process process in Process.GetProcessesByName("your_script")) { process.Kill(); } } }
- 第四步:打包Unity应用的时候,确保
StreamingAssets文件夹被正确包含(Unity默认会打包这个文件夹里的内容)。打包完成后,Unity EXE会在启动时自动启动Python EXE,两者通过socket正常通信,用户只需要双击一个EXE就行。
方案二:将Python解释器嵌入Unity(无需单独Python进程)
如果不想启动单独的Python进程,可以把Python解释器嵌入到Unity里,直接在C#中调用Python代码,这样连socket都可以省掉,用内存通信更高效:
- 第一步:下载
pythonnet的对应版本(要和Unity的.NET版本匹配,比如Unity用.NET Framework 4.x就下载对应版本的pythonnet),把Python.Runtime.dll等相关文件放到Unity的Plugins文件夹里。 - 第二步:把你的Python脚本和Python依赖库放到Unity的
StreamingAssets文件夹,同时把Python安装目录里的python39.dll(根据你的Python版本调整,比如python310.dll)也放进去。 - 第三步:在C#脚本中初始化Python解释器,导入并调用你的Python脚本。示例代码:
using Python.Runtime; using UnityEngine; using System.IO; public class PythonIntegrator : MonoBehaviour { void Start() { // 配置Python环境路径 Runtime.PythonDLL = Path.Combine(Application.streamingAssetsPath, "python39.dll"); // 设置Python的搜索路径,让解释器能找到你的脚本和依赖库 PythonEngine.PythonPath = Application.streamingAssetsPath; PythonEngine.Initialize(); // 导入你的Python脚本并调用方法 using (Py.GIL()) { dynamic script = Py.Import("your_script"); // 比如调用Python脚本里的启动服务方法 script.start_socket_server(); } } void OnApplicationQuit() { // 关闭Python解释器,释放资源 PythonEngine.Shutdown(); } }
- 注意:这个方案对Python的第三方库支持有限,如果你的脚本用到了很多复杂的原生库(比如OpenCV、TensorFlow),可能需要额外处理依赖打包,相对麻烦一点,但好处是没有单独的进程,整体更紧凑。
方案三:用自解压包打包所有文件
如果上面两个方案都不适合你,还可以用自解压工具把Unity EXE、Python EXE和启动器打包成一个文件:
- 第一步:分别打包Unity应用和Python脚本为独立的EXE。
- 第二步:写一个简单的C#控制台程序作为启动器,先启动Python EXE,等待3-5秒确保socket服务启动,再启动Unity EXE。
- 第三步:用7-Zip的自解压功能,把这三个文件打包成一个EXE,设置自解压后自动运行启动器,并且自解压到系统临时目录。这样用户双击这个自解压EXE后,会自动解压并启动启动器,进而依次启动Python和Unity。
一些关键注意事项
- 测试的时候一定要先在编辑器里验证socket通信正常,再打包测试,因为打包后的文件路径和编辑器里不一样,很容易出路径相关的问题。
- 打包Python脚本时,用
pyinstaller --onefile --windowed your_script.py可以隐藏Python的控制台窗口,避免用户看到多余的黑框。 - 处理socket连接时,要加异常捕获逻辑,比如如果Python进程启动失败,Unity要给用户友好提示,不要直接崩溃。
备注:内容来源于stack exchange,提问作者Mário Santana
相关产品推荐
相关产品推荐

