Skip to content

Commit efd146a

Browse files
committed
fix: Windows define UNITY_EDITOR_WIN; async stdout/stderr in TryRun and RepairPythonEnvironment; use EnvironmentVariables for PATH; prepend Unix PATH only on macOS/Linux; fix duplicate .meta GUIDs
1 parent f6f8b24 commit efd146a

File tree

5 files changed

+70
-26
lines changed

5 files changed

+70
-26
lines changed

UnityMcpBridge/Editor/Helpers/ExecPath.cs

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Diagnostics;
33
using System.IO;
44
using System.Linq;
5+
using System.Text;
56
using System.Runtime.InteropServices;
67
using UnityEditor;
78

@@ -43,7 +44,7 @@ internal static string ResolveClaude()
4344

4445
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
4546
{
46-
#if UNITY_EDITOR_WINDOWS
47+
#if UNITY_EDITOR_WIN
4748
// Common npm global locations
4849
string appData = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) ?? string.Empty;
4950
string localAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) ?? string.Empty;
@@ -109,16 +110,35 @@ internal static bool TryRun(
109110
if (!string.IsNullOrEmpty(extraPathPrepend))
110111
{
111112
string currentPath = Environment.GetEnvironmentVariable("PATH") ?? string.Empty;
112-
psi.Environment["PATH"] = string.IsNullOrEmpty(currentPath)
113+
psi.EnvironmentVariables["PATH"] = string.IsNullOrEmpty(currentPath)
113114
? extraPathPrepend
114115
: (extraPathPrepend + System.IO.Path.PathSeparator + currentPath);
115116
}
116-
using var p = Process.Start(psi);
117-
if (p == null) return false;
118-
stdout = p.StandardOutput.ReadToEnd();
119-
stderr = p.StandardError.ReadToEnd();
120-
if (!p.WaitForExit(timeoutMs)) { try { p.Kill(); } catch { } return false; }
121-
return p.ExitCode == 0;
117+
118+
using var process = new Process { StartInfo = psi, EnableRaisingEvents = false };
119+
120+
var so = new StringBuilder();
121+
var se = new StringBuilder();
122+
process.OutputDataReceived += (_, e) => { if (e.Data != null) so.AppendLine(e.Data); };
123+
process.ErrorDataReceived += (_, e) => { if (e.Data != null) se.AppendLine(e.Data); };
124+
125+
if (!process.Start()) return false;
126+
127+
process.BeginOutputReadLine();
128+
process.BeginErrorReadLine();
129+
130+
if (!process.WaitForExit(timeoutMs))
131+
{
132+
try { process.Kill(); } catch { }
133+
return false;
134+
}
135+
136+
// Ensure async buffers are flushed
137+
process.WaitForExit();
138+
139+
stdout = so.ToString();
140+
stderr = se.ToString();
141+
return process.ExitCode == 0;
122142
}
123143
catch
124144
{
@@ -138,7 +158,7 @@ private static string Which(string exe, string prependPath)
138158
CreateNoWindow = true,
139159
};
140160
string path = Environment.GetEnvironmentVariable("PATH") ?? string.Empty;
141-
psi.Environment["PATH"] = string.IsNullOrEmpty(path) ? prependPath : (prependPath + Path.PathSeparator + path);
161+
psi.EnvironmentVariables["PATH"] = string.IsNullOrEmpty(path) ? prependPath : (prependPath + Path.PathSeparator + path);
142162
using var p = Process.Start(psi);
143163
string output = p?.StandardOutput.ReadToEnd().Trim();
144164
p?.WaitForExit(1500);
@@ -148,7 +168,7 @@ private static string Which(string exe, string prependPath)
148168
}
149169
#endif
150170

151-
#if UNITY_EDITOR_WINDOWS
171+
#if UNITY_EDITOR_WIN
152172
private static string Where(string exe)
153173
{
154174
try

UnityMcpBridge/Editor/Helpers/ExecPath.cs.meta

Lines changed: 1 addition & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

UnityMcpBridge/Editor/Helpers/ServerInstaller.cs

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.IO;
33
using System.Runtime.InteropServices;
4+
using System.Text;
45
using System.Reflection;
56
using UnityEditor;
67
using UnityEngine;
@@ -206,12 +207,35 @@ public static bool RepairPythonEnvironment()
206207
CreateNoWindow = true
207208
};
208209

209-
using var p = System.Diagnostics.Process.Start(psi);
210-
string stdout = p.StandardOutput.ReadToEnd();
211-
string stderr = p.StandardError.ReadToEnd();
212-
p.WaitForExit(60000);
210+
using var proc = new System.Diagnostics.Process { StartInfo = psi };
211+
var sbOut = new StringBuilder();
212+
var sbErr = new StringBuilder();
213+
proc.OutputDataReceived += (_, e) => { if (e.Data != null) sbOut.AppendLine(e.Data); };
214+
proc.ErrorDataReceived += (_, e) => { if (e.Data != null) sbErr.AppendLine(e.Data); };
215+
216+
if (!proc.Start())
217+
{
218+
Debug.LogError("Failed to start uv process.");
219+
return false;
220+
}
221+
222+
proc.BeginOutputReadLine();
223+
proc.BeginErrorReadLine();
224+
225+
if (!proc.WaitForExit(60000))
226+
{
227+
try { proc.Kill(); } catch { }
228+
Debug.LogError("uv sync timed out.");
229+
return false;
230+
}
231+
232+
// Ensure async buffers flushed
233+
proc.WaitForExit();
234+
235+
string stdout = sbOut.ToString();
236+
string stderr = sbErr.ToString();
213237

214-
if (p.ExitCode != 0)
238+
if (proc.ExitCode != 0)
215239
{
216240
Debug.LogError($"uv sync failed: {stderr}\n{stdout}");
217241
return false;
@@ -341,7 +365,7 @@ internal static string FindUvPath()
341365
"/bin"
342366
});
343367
string currentPath = Environment.GetEnvironmentVariable("PATH") ?? string.Empty;
344-
whichPsi.Environment["PATH"] = string.IsNullOrEmpty(currentPath) ? prepend : (prepend + ":" + currentPath);
368+
whichPsi.EnvironmentVariables["PATH"] = string.IsNullOrEmpty(currentPath) ? prepend : (prepend + ":" + currentPath);
345369
}
346370
catch { }
347371
using var wp = System.Diagnostics.Process.Start(whichPsi);

UnityMcpBridge/Editor/Helpers/ServerPathResolver.cs.meta

Lines changed: 1 addition & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

UnityMcpBridge/Editor/Windows/UnityMcpEditorWindow.cs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1320,10 +1320,14 @@ private void RegisterWithClaudeCode(string pythonDir)
13201320
string args = $"mcp add UnityMCP -- \"{uvPath}\" run --directory \"{srcDir}\" server.py";
13211321

13221322
string projectDir = Path.GetDirectoryName(Application.dataPath);
1323-
// Ensure PATH includes common Node/npm locations so claude can spawn node internally if needed
1324-
string pathPrepend = Application.platform == RuntimePlatform.OSXEditor
1325-
? "/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin"
1326-
: "/usr/local/bin:/usr/bin:/bin";
1323+
// Ensure PATH includes common locations on Unix; on Windows leave PATH as-is
1324+
string pathPrepend = null;
1325+
if (Application.platform == RuntimePlatform.OSXEditor || Application.platform == RuntimePlatform.LinuxEditor)
1326+
{
1327+
pathPrepend = Application.platform == RuntimePlatform.OSXEditor
1328+
? "/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin"
1329+
: "/usr/local/bin:/usr/bin:/bin";
1330+
}
13271331
if (!ExecPath.TryRun(claudePath, args, projectDir, out var stdout, out var stderr, 15000, pathPrepend))
13281332
{
13291333
UnityEngine.Debug.LogError($"UnityMCP: Failed to start Claude CLI.\n{stderr}\n{stdout}");

0 commit comments

Comments
 (0)