commit
4aff62fe5c
|
|
@ -32,6 +32,7 @@ namespace UnityMCP.Editor.Commands
|
|||
"BUILD" => HandleBuild(commandParams),
|
||||
"EXECUTE_COMMAND" => HandleExecuteCommand(commandParams),
|
||||
"READ_CONSOLE" => ReadConsole(commandParams),
|
||||
"GET_AVAILABLE_COMMANDS" => GetAvailableCommands(),
|
||||
_ => new { error = $"Unknown editor control command: {command}" },
|
||||
};
|
||||
}
|
||||
|
|
@ -583,5 +584,367 @@ namespace UnityMCP.Editor.Commands
|
|||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a comprehensive list of available Unity commands, including editor menu items,
|
||||
/// internal commands, utility methods, and other actionable operations that can be executed.
|
||||
/// </summary>
|
||||
/// <returns>Object containing categorized lists of available command paths</returns>
|
||||
private static object GetAvailableCommands()
|
||||
{
|
||||
var menuCommands = new HashSet<string>();
|
||||
var utilityCommands = new HashSet<string>();
|
||||
var assetCommands = new HashSet<string>();
|
||||
var sceneCommands = new HashSet<string>();
|
||||
var gameObjectCommands = new HashSet<string>();
|
||||
var prefabCommands = new HashSet<string>();
|
||||
var shortcutCommands = new HashSet<string>();
|
||||
var otherCommands = new HashSet<string>();
|
||||
|
||||
// Add a simple command that we know will work for testing
|
||||
menuCommands.Add("Window/Unity MCP");
|
||||
|
||||
Debug.Log("Starting command collection...");
|
||||
|
||||
try
|
||||
{
|
||||
// Add all EditorApplication static methods - these are guaranteed to work
|
||||
Debug.Log("Adding EditorApplication methods...");
|
||||
foreach (MethodInfo method in typeof(EditorApplication).GetMethods(BindingFlags.Public | BindingFlags.Static))
|
||||
{
|
||||
utilityCommands.Add($"EditorApplication.{method.Name}");
|
||||
}
|
||||
Debug.Log($"Added {utilityCommands.Count} EditorApplication methods");
|
||||
|
||||
// Add built-in menu commands directly - these are common ones that should always be available
|
||||
Debug.Log("Adding built-in menu commands...");
|
||||
string[] builtInMenus = new[] {
|
||||
"File/New Scene",
|
||||
"File/Open Scene",
|
||||
"File/Save",
|
||||
"File/Save As...",
|
||||
"Edit/Undo",
|
||||
"Edit/Redo",
|
||||
"Edit/Cut",
|
||||
"Edit/Copy",
|
||||
"Edit/Paste",
|
||||
"Edit/Duplicate",
|
||||
"Edit/Delete",
|
||||
"GameObject/Create Empty",
|
||||
"GameObject/3D Object/Cube",
|
||||
"GameObject/3D Object/Sphere",
|
||||
"GameObject/3D Object/Capsule",
|
||||
"GameObject/3D Object/Cylinder",
|
||||
"GameObject/3D Object/Plane",
|
||||
"GameObject/Light/Directional Light",
|
||||
"GameObject/Light/Point Light",
|
||||
"GameObject/Light/Spotlight",
|
||||
"GameObject/Light/Area Light",
|
||||
"Component/Mesh/Mesh Filter",
|
||||
"Component/Mesh/Mesh Renderer",
|
||||
"Component/Physics/Rigidbody",
|
||||
"Component/Physics/Box Collider",
|
||||
"Component/Physics/Sphere Collider",
|
||||
"Component/Physics/Capsule Collider",
|
||||
"Component/Audio/Audio Source",
|
||||
"Component/Audio/Audio Listener",
|
||||
"Window/General/Scene",
|
||||
"Window/General/Game",
|
||||
"Window/General/Inspector",
|
||||
"Window/General/Hierarchy",
|
||||
"Window/General/Project",
|
||||
"Window/General/Console",
|
||||
"Window/Analysis/Profiler",
|
||||
"Window/Package Manager",
|
||||
"Assets/Create/Material",
|
||||
"Assets/Create/C# Script",
|
||||
"Assets/Create/Prefab",
|
||||
"Assets/Create/Scene",
|
||||
"Assets/Create/Folder",
|
||||
};
|
||||
|
||||
foreach (string menuItem in builtInMenus)
|
||||
{
|
||||
menuCommands.Add(menuItem);
|
||||
}
|
||||
Debug.Log($"Added {builtInMenus.Length} built-in menu commands");
|
||||
|
||||
// Get menu commands from MenuItem attributes - wrapped in separate try block
|
||||
Debug.Log("Searching for MenuItem attributes...");
|
||||
try
|
||||
{
|
||||
int itemCount = 0;
|
||||
foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
|
||||
{
|
||||
if (assembly.IsDynamic) continue;
|
||||
|
||||
try
|
||||
{
|
||||
foreach (Type type in assembly.GetExportedTypes())
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (MethodInfo method in type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic))
|
||||
{
|
||||
try
|
||||
{
|
||||
object[] attributes = method.GetCustomAttributes(typeof(UnityEditor.MenuItem), false);
|
||||
if (attributes != null && attributes.Length > 0)
|
||||
{
|
||||
foreach (var attr in attributes)
|
||||
{
|
||||
var menuItem = attr as UnityEditor.MenuItem;
|
||||
if (menuItem != null && !string.IsNullOrEmpty(menuItem.menuItem))
|
||||
{
|
||||
menuCommands.Add(menuItem.menuItem);
|
||||
itemCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception methodEx)
|
||||
{
|
||||
Debug.LogWarning($"Error getting menu items for method {method.Name}: {methodEx.Message}");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception typeEx)
|
||||
{
|
||||
Debug.LogWarning($"Error processing type: {typeEx.Message}");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception assemblyEx)
|
||||
{
|
||||
Debug.LogWarning($"Error examining assembly {assembly.GetName().Name}: {assemblyEx.Message}");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
Debug.Log($"Found {itemCount} menu items from attributes");
|
||||
}
|
||||
catch (Exception menuItemEx)
|
||||
{
|
||||
Debug.LogError($"Failed to get menu items: {menuItemEx.Message}");
|
||||
}
|
||||
|
||||
// Add EditorUtility methods as commands
|
||||
Debug.Log("Adding EditorUtility methods...");
|
||||
foreach (MethodInfo method in typeof(EditorUtility).GetMethods(BindingFlags.Public | BindingFlags.Static))
|
||||
{
|
||||
utilityCommands.Add($"EditorUtility.{method.Name}");
|
||||
}
|
||||
Debug.Log($"Added {typeof(EditorUtility).GetMethods(BindingFlags.Public | BindingFlags.Static).Length} EditorUtility methods");
|
||||
|
||||
// Add AssetDatabase methods as commands
|
||||
Debug.Log("Adding AssetDatabase methods...");
|
||||
foreach (MethodInfo method in typeof(AssetDatabase).GetMethods(BindingFlags.Public | BindingFlags.Static))
|
||||
{
|
||||
assetCommands.Add($"AssetDatabase.{method.Name}");
|
||||
}
|
||||
Debug.Log($"Added {typeof(AssetDatabase).GetMethods(BindingFlags.Public | BindingFlags.Static).Length} AssetDatabase methods");
|
||||
|
||||
// Add EditorSceneManager methods as commands
|
||||
Debug.Log("Adding EditorSceneManager methods...");
|
||||
Type sceneManagerType = typeof(UnityEditor.SceneManagement.EditorSceneManager);
|
||||
if (sceneManagerType != null)
|
||||
{
|
||||
foreach (MethodInfo method in sceneManagerType.GetMethods(BindingFlags.Public | BindingFlags.Static))
|
||||
{
|
||||
sceneCommands.Add($"EditorSceneManager.{method.Name}");
|
||||
}
|
||||
Debug.Log($"Added {sceneManagerType.GetMethods(BindingFlags.Public | BindingFlags.Static).Length} EditorSceneManager methods");
|
||||
}
|
||||
|
||||
// Add GameObject manipulation commands
|
||||
Debug.Log("Adding GameObject methods...");
|
||||
foreach (MethodInfo method in typeof(GameObject).GetMethods(BindingFlags.Public | BindingFlags.Static))
|
||||
{
|
||||
gameObjectCommands.Add($"GameObject.{method.Name}");
|
||||
}
|
||||
Debug.Log($"Added {typeof(GameObject).GetMethods(BindingFlags.Public | BindingFlags.Static).Length} GameObject methods");
|
||||
|
||||
// Add Selection-related commands
|
||||
Debug.Log("Adding Selection methods...");
|
||||
foreach (MethodInfo method in typeof(Selection).GetMethods(BindingFlags.Public | BindingFlags.Static))
|
||||
{
|
||||
gameObjectCommands.Add($"Selection.{method.Name}");
|
||||
}
|
||||
Debug.Log($"Added {typeof(Selection).GetMethods(BindingFlags.Public | BindingFlags.Static).Length} Selection methods");
|
||||
|
||||
// Add PrefabUtility methods as commands
|
||||
Debug.Log("Adding PrefabUtility methods...");
|
||||
Type prefabUtilityType = typeof(UnityEditor.PrefabUtility);
|
||||
if (prefabUtilityType != null)
|
||||
{
|
||||
foreach (MethodInfo method in prefabUtilityType.GetMethods(BindingFlags.Public | BindingFlags.Static))
|
||||
{
|
||||
prefabCommands.Add($"PrefabUtility.{method.Name}");
|
||||
}
|
||||
Debug.Log($"Added {prefabUtilityType.GetMethods(BindingFlags.Public | BindingFlags.Static).Length} PrefabUtility methods");
|
||||
}
|
||||
|
||||
// Add Undo related methods
|
||||
Debug.Log("Adding Undo methods...");
|
||||
foreach (MethodInfo method in typeof(Undo).GetMethods(BindingFlags.Public | BindingFlags.Static))
|
||||
{
|
||||
utilityCommands.Add($"Undo.{method.Name}");
|
||||
}
|
||||
Debug.Log($"Added {typeof(Undo).GetMethods(BindingFlags.Public | BindingFlags.Static).Length} Undo methods");
|
||||
|
||||
// The rest of the command gathering can be attempted but might not be critical
|
||||
try
|
||||
{
|
||||
// Get commands from Unity's internal command system
|
||||
Debug.Log("Trying to get internal CommandService commands...");
|
||||
Type commandServiceType = typeof(UnityEditor.EditorWindow).Assembly.GetType("UnityEditor.CommandService");
|
||||
if (commandServiceType != null)
|
||||
{
|
||||
Debug.Log("Found CommandService type");
|
||||
PropertyInfo instanceProperty = commandServiceType.GetProperty("Instance",
|
||||
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
|
||||
|
||||
if (instanceProperty != null)
|
||||
{
|
||||
Debug.Log("Found Instance property");
|
||||
object commandService = instanceProperty.GetValue(null);
|
||||
if (commandService != null)
|
||||
{
|
||||
Debug.Log("Got CommandService instance");
|
||||
MethodInfo findAllCommandsMethod = commandServiceType.GetMethod("FindAllCommands",
|
||||
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
|
||||
if (findAllCommandsMethod != null)
|
||||
{
|
||||
Debug.Log("Found FindAllCommands method");
|
||||
var commandsResult = findAllCommandsMethod.Invoke(commandService, null);
|
||||
if (commandsResult != null)
|
||||
{
|
||||
Debug.Log("Got commands result");
|
||||
var commandsList = commandsResult as System.Collections.IEnumerable;
|
||||
if (commandsList != null)
|
||||
{
|
||||
int commandCount = 0;
|
||||
foreach (var cmd in commandsList)
|
||||
{
|
||||
try
|
||||
{
|
||||
PropertyInfo nameProperty = cmd.GetType().GetProperty("name") ??
|
||||
cmd.GetType().GetProperty("path") ??
|
||||
cmd.GetType().GetProperty("commandName");
|
||||
if (nameProperty != null)
|
||||
{
|
||||
string commandName = nameProperty.GetValue(cmd)?.ToString();
|
||||
if (!string.IsNullOrEmpty(commandName))
|
||||
{
|
||||
otherCommands.Add(commandName);
|
||||
commandCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception cmdEx)
|
||||
{
|
||||
Debug.LogWarning($"Error processing command: {cmdEx.Message}");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
Debug.Log($"Added {commandCount} internal commands");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning("FindAllCommands returned null");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning("FindAllCommands method not found");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning("CommandService instance is null");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning("Instance property not found on CommandService");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning("CommandService type not found");
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogWarning($"Failed to get internal Unity commands: {e.Message}");
|
||||
}
|
||||
|
||||
// Other additional command sources can be tried
|
||||
// ... other commands ...
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError($"Error getting Unity commands: {e.Message}\n{e.StackTrace}");
|
||||
}
|
||||
|
||||
// Create command categories dictionary for the result
|
||||
var commandCategories = new Dictionary<string, List<string>>
|
||||
{
|
||||
{ "MenuCommands", menuCommands.OrderBy(x => x).ToList() },
|
||||
{ "UtilityCommands", utilityCommands.OrderBy(x => x).ToList() },
|
||||
{ "AssetCommands", assetCommands.OrderBy(x => x).ToList() },
|
||||
{ "SceneCommands", sceneCommands.OrderBy(x => x).ToList() },
|
||||
{ "GameObjectCommands", gameObjectCommands.OrderBy(x => x).ToList() },
|
||||
{ "PrefabCommands", prefabCommands.OrderBy(x => x).ToList() },
|
||||
{ "ShortcutCommands", shortcutCommands.OrderBy(x => x).ToList() },
|
||||
{ "OtherCommands", otherCommands.OrderBy(x => x).ToList() }
|
||||
};
|
||||
|
||||
// Calculate total command count
|
||||
int totalCount = commandCategories.Values.Sum(list => list.Count);
|
||||
|
||||
Debug.Log($"Command retrieval complete. Found {totalCount} total commands.");
|
||||
|
||||
// Create a simplified response with just the essential data
|
||||
// The complex object structure might be causing serialization issues
|
||||
var allCommandsList = commandCategories.Values.SelectMany(x => x).OrderBy(x => x).ToList();
|
||||
|
||||
// Use simple string array instead of JArray for better serialization
|
||||
string[] commandsArray = allCommandsList.ToArray();
|
||||
|
||||
// Log the array size for verification
|
||||
Debug.Log($"Final commands array contains {commandsArray.Length} items");
|
||||
|
||||
try
|
||||
{
|
||||
// Return a simple object with just the commands array and count
|
||||
var result = new
|
||||
{
|
||||
commands = commandsArray,
|
||||
count = commandsArray.Length
|
||||
};
|
||||
|
||||
// Verify the result can be serialized properly
|
||||
var jsonTest = JsonUtility.ToJson(new { test = "This is a test" });
|
||||
Debug.Log($"JSON serialization test successful: {jsonTest}");
|
||||
|
||||
return result;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogError($"Error creating response: {ex.Message}");
|
||||
|
||||
// Ultimate fallback - don't use any JObject/JArray
|
||||
return new
|
||||
{
|
||||
message = $"Found {commandsArray.Length} commands",
|
||||
firstTen = commandsArray.Take(10).ToArray(),
|
||||
count = commandsArray.Length
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -7,6 +7,7 @@ using UnityEditor;
|
|||
using UnityEngine.SceneManagement;
|
||||
using UnityEditor.SceneManagement;
|
||||
using UnityMCP.Editor.Helpers;
|
||||
using System.Reflection;
|
||||
|
||||
namespace UnityMCP.Editor.Commands
|
||||
{
|
||||
|
|
@ -398,5 +399,107 @@ namespace UnityMCP.Editor.Commands
|
|||
light.shadows = LightShadows.Soft;
|
||||
return obj;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes a context menu method on a component of a game object
|
||||
/// </summary>
|
||||
public static object ExecuteContextMenuItem(JObject @params)
|
||||
{
|
||||
string objectName = (string)@params["object_name"] ?? throw new Exception("Parameter 'object_name' is required.");
|
||||
string componentName = (string)@params["component"] ?? throw new Exception("Parameter 'component' is required.");
|
||||
string contextMenuItemName = (string)@params["context_menu_item"] ?? throw new Exception("Parameter 'context_menu_item' is required.");
|
||||
|
||||
// Find the game object
|
||||
var obj = GameObject.Find(objectName) ?? throw new Exception($"Object '{objectName}' not found.");
|
||||
|
||||
// Find the component type
|
||||
Type componentType = FindTypeInLoadedAssemblies(componentName) ??
|
||||
throw new Exception($"Component type '{componentName}' not found.");
|
||||
|
||||
// Get the component from the game object
|
||||
var component = obj.GetComponent(componentType) ??
|
||||
throw new Exception($"Component '{componentName}' not found on object '{objectName}'.");
|
||||
|
||||
// Find methods with ContextMenu attribute matching the context menu item name
|
||||
var methods = componentType.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
|
||||
.Where(m => m.GetCustomAttributes(typeof(ContextMenuItemAttribute), true).Any() ||
|
||||
m.GetCustomAttributes(typeof(ContextMenu), true)
|
||||
.Cast<ContextMenu>()
|
||||
.Any(attr => attr.menuItem == contextMenuItemName))
|
||||
.ToList();
|
||||
|
||||
// If no methods with ContextMenuItemAttribute are found, look for methods with name matching the context menu item
|
||||
if (methods.Count == 0)
|
||||
{
|
||||
methods = componentType.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
|
||||
.Where(m => m.Name == contextMenuItemName)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
if (methods.Count == 0)
|
||||
throw new Exception($"No context menu method '{contextMenuItemName}' found on component '{componentName}'.");
|
||||
|
||||
// If multiple methods match, use the first one and log a warning
|
||||
if (methods.Count > 1)
|
||||
{
|
||||
Debug.LogWarning($"Found multiple methods for context menu item '{contextMenuItemName}' on component '{componentName}'. Using the first one.");
|
||||
}
|
||||
|
||||
var method = methods[0];
|
||||
|
||||
// Execute the method
|
||||
try
|
||||
{
|
||||
method.Invoke(component, null);
|
||||
return new
|
||||
{
|
||||
success = true,
|
||||
message = $"Successfully executed context menu item '{contextMenuItemName}' on component '{componentName}' of object '{objectName}'."
|
||||
};
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception($"Error executing context menu item: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
// Add this helper method to find types across all loaded assemblies
|
||||
private static Type FindTypeInLoadedAssemblies(string typeName)
|
||||
{
|
||||
// First try standard approach
|
||||
Type type = Type.GetType(typeName);
|
||||
if (type != null)
|
||||
return type;
|
||||
|
||||
type = Type.GetType($"UnityEngine.{typeName}");
|
||||
if (type != null)
|
||||
return type;
|
||||
|
||||
// Then search all loaded assemblies
|
||||
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
|
||||
{
|
||||
// Try with the simple name
|
||||
type = assembly.GetType(typeName);
|
||||
if (type != null)
|
||||
return type;
|
||||
|
||||
// Try with the fully qualified name (assembly.GetTypes() can be expensive, so we do this last)
|
||||
var types = assembly.GetTypes().Where(t => t.Name == typeName).ToArray();
|
||||
|
||||
if (types.Length > 0)
|
||||
{
|
||||
// If we found multiple types with the same name, log a warning
|
||||
if (types.Length > 1)
|
||||
{
|
||||
Debug.LogWarning(
|
||||
$"Found multiple types named '{typeName}'. Using the first one: {types[0].FullName}"
|
||||
);
|
||||
}
|
||||
return types[0];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -286,6 +286,7 @@ namespace UnityMCP.Editor
|
|||
"CREATE_OBJECT" => ObjectCommandHandler.CreateObject(command.@params),
|
||||
"MODIFY_OBJECT" => ObjectCommandHandler.ModifyObject(command.@params),
|
||||
"DELETE_OBJECT" => ObjectCommandHandler.DeleteObject(command.@params),
|
||||
"EXECUTE_CONTEXT_MENU_ITEM" => ObjectCommandHandler.ExecuteContextMenuItem(command.@params),
|
||||
"GET_OBJECT_PROPERTIES" => ObjectCommandHandler.GetObjectProperties(command.@params),
|
||||
"GET_COMPONENT_PROPERTIES" => ObjectCommandHandler.GetComponentProperties(command.@params),
|
||||
"FIND_OBJECTS_BY_NAME" => ObjectCommandHandler.FindObjectsByName(command.@params),
|
||||
|
|
|
|||
|
|
@ -266,4 +266,30 @@ def register_editor_tools(mcp: FastMCP):
|
|||
"type": "Error",
|
||||
"message": f"Error reading console: {str(e)}",
|
||||
"stackTrace": ""
|
||||
}]
|
||||
}]
|
||||
|
||||
@mcp.tool()
|
||||
def get_available_commands(ctx: Context) -> List[str]:
|
||||
"""Get a list of all available editor commands that can be executed.
|
||||
|
||||
This tool provides direct access to the list of commands that can be executed
|
||||
in the Unity Editor through the MCP system.
|
||||
|
||||
Returns:
|
||||
List[str]: List of available command paths
|
||||
"""
|
||||
try:
|
||||
unity = get_unity_connection()
|
||||
|
||||
# Send request for available commands
|
||||
response = unity.send_command("EDITOR_CONTROL", {
|
||||
"command": "GET_AVAILABLE_COMMANDS"
|
||||
})
|
||||
|
||||
# Extract commands list
|
||||
commands = response.get("commands", [])
|
||||
|
||||
# Return the commands list
|
||||
return commands
|
||||
except Exception as e:
|
||||
return [f"Error fetching commands: {str(e)}"]
|
||||
|
|
@ -194,4 +194,57 @@ def register_object_tools(mcp: FastMCP):
|
|||
})
|
||||
return response.get("assets", [])
|
||||
except Exception as e:
|
||||
return [{"error": f"Failed to get asset list: {str(e)}"}]
|
||||
return [{"error": f"Failed to get asset list: {str(e)}"}]
|
||||
|
||||
@mcp.tool()
|
||||
def execute_context_menu_item(
|
||||
ctx: Context,
|
||||
object_name: str,
|
||||
component: str,
|
||||
context_menu_item: str
|
||||
) -> Dict[str, Any]:
|
||||
"""Execute a specific [ContextMenu] method on a component of a given game object.
|
||||
|
||||
Args:
|
||||
ctx: The MCP context
|
||||
object_name: Name of the game object to call
|
||||
component: Name of the component type
|
||||
context_menu_item: Name of the context menu item to execute
|
||||
|
||||
Returns:
|
||||
Dict containing the result of the operation
|
||||
"""
|
||||
try:
|
||||
unity = get_unity_connection()
|
||||
|
||||
# Check if the object exists
|
||||
found_objects = unity.send_command("FIND_OBJECTS_BY_NAME", {
|
||||
"name": object_name
|
||||
}).get("objects", [])
|
||||
|
||||
if not found_objects:
|
||||
return {"error": f"Object with name '{object_name}' not found in the scene."}
|
||||
|
||||
# Check if the component exists on the object
|
||||
object_props = unity.send_command("GET_OBJECT_PROPERTIES", {
|
||||
"name": object_name
|
||||
})
|
||||
|
||||
if "error" in object_props:
|
||||
return {"error": f"Failed to get object properties: {object_props['error']}"}
|
||||
|
||||
components = object_props.get("components", [])
|
||||
component_exists = any(comp.get("type") == component for comp in components)
|
||||
|
||||
if not component_exists:
|
||||
return {"error": f"Component '{component}' is not attached to object '{object_name}'."}
|
||||
|
||||
# Now execute the context menu item
|
||||
response = unity.send_command("EXECUTE_CONTEXT_MENU_ITEM", {
|
||||
"object_name": object_name,
|
||||
"component": component,
|
||||
"context_menu_item": context_menu_item
|
||||
})
|
||||
return response
|
||||
except Exception as e:
|
||||
return {"error": f"Failed to execute context menu item: {str(e)}"}
|
||||
Loading…
Reference in New Issue