Skip to main content
Glama
EditorPlayModeControl.cs11.3 kB
using System; using UnityEngine; #if UNITY_EDITOR using UnityEditor; #endif namespace LocalMcp.UnityServer { #if UNITY_EDITOR /// <summary> /// Controls Unity Editor Play Mode (Start/Stop game) /// </summary> public static class EditorPlayModeControl { /// <summary> /// Starts Play Mode /// </summary> public static string Play(object id) { try { if (EditorApplication.isPlaying) { var result = new PlayModeResult { success = false, message = "Already in Play Mode", isPlaying = true, isPaused = EditorApplication.isPaused }; var response = JsonRpcResponse.Success(result, id); return response.ToJson(); } EditorApplication.isPlaying = true; var successResult = new PlayModeResult { success = true, message = "Play Mode started", isPlaying = true, isPaused = false }; var successResponse = JsonRpcResponse.Success(successResult, id); return successResponse.ToJson(); } catch (Exception e) { Debug.LogError($"[MCP] Play error: {e.Message}\n{e.StackTrace}"); return JsonRpcResponseHelper.ErrorMessage($"Failed to start Play Mode: {e.Message}", id); } } /// <summary> /// Stops Play Mode /// </summary> public static string Stop(object id) { try { if (!EditorApplication.isPlaying) { var result = new PlayModeResult { success = false, message = "Not in Play Mode", isPlaying = false, isPaused = false }; var response = JsonRpcResponse.Success(result, id); return response.ToJson(); } EditorApplication.isPlaying = false; var successResult = new PlayModeResult { success = true, message = "Play Mode stopped", isPlaying = false, isPaused = false }; var successResponse = JsonRpcResponse.Success(successResult, id); return successResponse.ToJson(); } catch (Exception e) { Debug.LogError($"[MCP] Stop error: {e.Message}\n{e.StackTrace}"); return JsonRpcResponseHelper.ErrorMessage($"Failed to stop Play Mode: {e.Message}", id); } } /// <summary> /// Pauses Play Mode /// </summary> public static string Pause(object id) { try { if (!EditorApplication.isPlaying) { return JsonRpcResponseHelper.ErrorMessage("Not in Play Mode", id); } EditorApplication.isPaused = true; var result = new PlayModeResult { success = true, message = "Play Mode paused", isPlaying = true, isPaused = true }; var response = JsonRpcResponse.Success(result, id); return response.ToJson(); } catch (Exception e) { Debug.LogError($"[MCP] Pause error: {e.Message}\n{e.StackTrace}"); return JsonRpcResponseHelper.ErrorMessage($"Failed to pause Play Mode: {e.Message}", id); } } /// <summary> /// Resumes Play Mode from pause /// </summary> public static string Resume(object id) { try { if (!EditorApplication.isPlaying) { return JsonRpcResponseHelper.ErrorMessage("Not in Play Mode", id); } if (!EditorApplication.isPaused) { var result = new PlayModeResult { success = false, message = "Play Mode is not paused", isPlaying = true, isPaused = false }; var response = JsonRpcResponse.Success(result, id); return response.ToJson(); } EditorApplication.isPaused = false; var successResult = new PlayModeResult { success = true, message = "Play Mode resumed", isPlaying = true, isPaused = false }; var successResponse = JsonRpcResponse.Success(successResult, id); return successResponse.ToJson(); } catch (Exception e) { Debug.LogError($"[MCP] Resume error: {e.Message}\n{e.StackTrace}"); return JsonRpcResponseHelper.ErrorMessage($"Failed to resume Play Mode: {e.Message}", id); } } /// <summary> /// Steps one frame forward in paused Play Mode /// </summary> public static string Step(object id) { try { if (!EditorApplication.isPlaying) { return JsonRpcResponseHelper.ErrorMessage("Not in Play Mode", id); } if (!EditorApplication.isPaused) { return JsonRpcResponseHelper.ErrorMessage("Play Mode is not paused. Pause first to step.", id); } EditorApplication.Step(); var result = new PlayModeResult { success = true, message = "Stepped one frame", isPlaying = true, isPaused = true }; var response = JsonRpcResponse.Success(result, id); return response.ToJson(); } catch (Exception e) { Debug.LogError($"[MCP] Step error: {e.Message}\n{e.StackTrace}"); return JsonRpcResponseHelper.ErrorMessage($"Failed to step frame: {e.Message}", id); } } /// <summary> /// Gets the current Play Mode status /// </summary> public static string GetStatus(object id) { try { var result = new PlayModeStatusResult { isPlaying = EditorApplication.isPlaying, isPaused = EditorApplication.isPaused, isCompiling = EditorApplication.isCompiling, isPlayingOrWillChangePlaymode = EditorApplication.isPlayingOrWillChangePlaymode }; var response = JsonRpcResponse.Success(result, id); return response.ToJson(); } catch (Exception e) { Debug.LogError($"[MCP] GetStatus error: {e.Message}\n{e.StackTrace}"); return JsonRpcResponseHelper.ErrorMessage($"Failed to get Play Mode status: {e.Message}", id); } } /// <summary> /// Plays for a specified duration and captures logs /// </summary> public static string PlayAndCaptureLogs(string paramsJson, object id) { try { var parameters = JsonUtility.FromJson<PlayAndCaptureLogsParams>(paramsJson); if (EditorApplication.isPlaying) { return JsonRpcResponseHelper.ErrorMessage("Already in Play Mode. Stop first before using this command.", id); } float duration = parameters.duration > 0 ? parameters.duration : 5.0f; int logLimit = parameters.logLimit > 0 ? parameters.logLimit : 100; string logLevel = string.IsNullOrEmpty(parameters.logLevel) ? "all" : parameters.logLevel; // Start Play Mode EditorApplication.isPlaying = true; // Schedule stop after duration double startTime = EditorApplication.timeSinceStartup; EditorApplication.update += CheckStopTime; void CheckStopTime() { if (EditorApplication.timeSinceStartup - startTime >= duration) { EditorApplication.update -= CheckStopTime; if (EditorApplication.isPlaying) { EditorApplication.isPlaying = false; } Debug.Log($"[MCP] PlayAndCaptureLogs: Stopped after {duration} seconds"); } } var result = new PlayAndCaptureLogsResult { success = true, message = $"Play Mode started for {duration} seconds. Will stop automatically.", duration = duration, logLimit = logLimit, logLevel = logLevel, instruction = $"Use unity.log.history with limit={logLimit} and level={logLevel} after {duration} seconds to retrieve logs" }; var response = JsonRpcResponse.Success(result, id); return response.ToJson(); } catch (Exception e) { Debug.LogError($"[MCP] PlayAndCaptureLogs error: {e.Message}\n{e.StackTrace}"); return JsonRpcResponseHelper.ErrorMessage($"Failed to play and capture logs: {e.Message}", id); } } } #region Data Structures [Serializable] public class PlayModeResult { public bool success; public string message; public bool isPlaying; public bool isPaused; } [Serializable] public class PlayModeStatusResult { public bool isPlaying; public bool isPaused; public bool isCompiling; public bool isPlayingOrWillChangePlaymode; } [Serializable] public class PlayAndCaptureLogsParams { public float duration; // Duration in seconds to play (default: 5.0) public int logLimit; // Number of logs to capture (default: 100) public string logLevel; // Log level filter: "all", "error", "warning", "log" (default: "all") } [Serializable] public class PlayAndCaptureLogsResult { public bool success; public string message; public float duration; public int logLimit; public string logLevel; public string instruction; } #endregion #endif }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/dsgarage/UniMCP4CC'

If you have feedback or need assistance with the MCP directory API, please join our Discord server