转自:https://networm.me/2019/06/09/kill-open-unity-process/
进行自动化打包时,需要将打开当前项目的 Unity 进程关掉,否则 Unity 会报告同一个项目不能开启多个 Unity 进程。
It looks like another Unity instance is running with this project open.
Multiple Unity instances cannot open the same project.
If you are sure that there is no running Unity instance with the project open, remove /UnityProject/Temp/UnityLockfile and restart Unity.
Project: /UnityProject
理论上支持 Unity、Windows、macOS 任意版本。
Library/EditorInstance.json
Unity 在启动后会在 Library/EditorInstance.json
文件中记录当前打开进程的 ID 信息,可是问题 Windows 与 macOS 下大部分情况下都不会生成此文件,原因不明。
此机制并不是十分可靠,因此排除。
在编写打包脚本启动 Unity 进程时,可以记录返回的进程 ID 并保存在文件中,用作下一次打包时关闭进程使用。
可依然存在问题,如果有人手动使用 Unity 打开了当前项目,打包依然会失败。
Temp/UnityLockfile
的进程默认情况下 Unity 打开项目时会创建此文件并保持打开状态。因此通过遍历操作系统内的所有名字为 Unity 的进程,查找其打开的文件中是否有当前项目的 Temp/UnityLockfile
文件,如果有则将进程杀掉。
这种方法可以同时适用于 Windows 与 macOS,稳定实用。
使用 psutil
这个跨平台的 Python 库即可轻松解决此问题。这个库的主要功能是封装了不同平台下操作进程的统一接口。
不同操作系统上安装的时候会携带不同的 Native 库,因此需要在所有要支持的平台上安装并提交。
注意:
Temp
目录及其内容,否则打开 Unity 时依然会有错误提示。Temp/UnityLockfile
时会提示文件被占用。def kill_unity(project_path):
unity_lockfile = os.path.abspath(os.path.join(project_path, 'Temp/UnityLockfile'))
if not os.path.exists(unity_lockfile):
return
if platform.system() == 'Windows':
unity_name = 'Unity.exe'
else:
unity_name = 'Unity'
for proc in psutil.process_iter():
try:
if proc.name() != unity_name:
continue
# this returns the list of opened files by the current process
open_files = proc.open_files()
if not open_files:
continue
found = False
for open_file in open_files:
if os.path.abspath(open_file.path) != unity_lockfile:
continue
found = True
print(f'Kill open Unity process: {proc.pid}')
sys.stdout.flush()
proc.kill()
# Wait for OS to terminate process and close open files
time.sleep(1)
break
if found:
break
# This catches a race condition where a process ends
# before we can examine its files
except psutil.NoSuchProcess as err:
print("****", err)
shutil.rmtree(os.path.join(project_path, 'Temp'))