@akiojin/unity-mcp-server 2.14.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (125) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +206 -0
  3. package/bin/unity-mcp-server +2 -0
  4. package/package.json +73 -0
  5. package/src/core/codeIndex.js +163 -0
  6. package/src/core/codeIndexDb.js +96 -0
  7. package/src/core/config.js +165 -0
  8. package/src/core/indexWatcher.js +52 -0
  9. package/src/core/projectInfo.js +111 -0
  10. package/src/core/server.js +294 -0
  11. package/src/core/unityConnection.js +426 -0
  12. package/src/handlers/analysis/AnalyzeSceneContentsToolHandler.js +35 -0
  13. package/src/handlers/analysis/FindByComponentToolHandler.js +20 -0
  14. package/src/handlers/analysis/GetAnimatorStateToolHandler.js +37 -0
  15. package/src/handlers/analysis/GetComponentValuesToolHandler.js +20 -0
  16. package/src/handlers/analysis/GetGameObjectDetailsToolHandler.js +35 -0
  17. package/src/handlers/analysis/GetInputActionsStateToolHandler.js +37 -0
  18. package/src/handlers/analysis/GetObjectReferencesToolHandler.js +20 -0
  19. package/src/handlers/asset/AssetDatabaseToolHandler.js +221 -0
  20. package/src/handlers/asset/AssetDependencyToolHandler.js +201 -0
  21. package/src/handlers/asset/AssetImportSettingsToolHandler.js +170 -0
  22. package/src/handlers/asset/CreateMaterialToolHandler.js +96 -0
  23. package/src/handlers/asset/CreatePrefabToolHandler.js +78 -0
  24. package/src/handlers/asset/ExitPrefabModeToolHandler.js +83 -0
  25. package/src/handlers/asset/InstantiatePrefabToolHandler.js +133 -0
  26. package/src/handlers/asset/ModifyMaterialToolHandler.js +76 -0
  27. package/src/handlers/asset/ModifyPrefabToolHandler.js +72 -0
  28. package/src/handlers/asset/OpenPrefabToolHandler.js +121 -0
  29. package/src/handlers/asset/SavePrefabToolHandler.js +106 -0
  30. package/src/handlers/base/BaseToolHandler.js +133 -0
  31. package/src/handlers/compilation/GetCompilationStateToolHandler.js +90 -0
  32. package/src/handlers/component/AddComponentToolHandler.js +126 -0
  33. package/src/handlers/component/GetComponentTypesToolHandler.js +100 -0
  34. package/src/handlers/component/ListComponentsToolHandler.js +85 -0
  35. package/src/handlers/component/ModifyComponentToolHandler.js +143 -0
  36. package/src/handlers/component/RemoveComponentToolHandler.js +108 -0
  37. package/src/handlers/console/ClearConsoleToolHandler.js +160 -0
  38. package/src/handlers/console/ReadConsoleToolHandler.js +276 -0
  39. package/src/handlers/editor/LayerManagementToolHandler.js +160 -0
  40. package/src/handlers/editor/SelectionToolHandler.js +141 -0
  41. package/src/handlers/editor/TagManagementToolHandler.js +129 -0
  42. package/src/handlers/editor/ToolManagementToolHandler.js +135 -0
  43. package/src/handlers/editor/WindowManagementToolHandler.js +125 -0
  44. package/src/handlers/gameobject/CreateGameObjectToolHandler.js +131 -0
  45. package/src/handlers/gameobject/DeleteGameObjectToolHandler.js +101 -0
  46. package/src/handlers/gameobject/FindGameObjectToolHandler.js +119 -0
  47. package/src/handlers/gameobject/GetHierarchyToolHandler.js +132 -0
  48. package/src/handlers/gameobject/ModifyGameObjectToolHandler.js +128 -0
  49. package/src/handlers/index.js +389 -0
  50. package/src/handlers/input/AddInputActionToolHandler.js +20 -0
  51. package/src/handlers/input/AddInputBindingToolHandler.js +20 -0
  52. package/src/handlers/input/CreateActionMapToolHandler.js +20 -0
  53. package/src/handlers/input/CreateCompositeBindingToolHandler.js +20 -0
  54. package/src/handlers/input/GamepadSimulationHandler.js +116 -0
  55. package/src/handlers/input/InputSystemHandler.js +80 -0
  56. package/src/handlers/input/KeyboardSimulationHandler.js +79 -0
  57. package/src/handlers/input/ManageControlSchemesToolHandler.js +20 -0
  58. package/src/handlers/input/MouseSimulationHandler.js +107 -0
  59. package/src/handlers/input/RemoveActionMapToolHandler.js +20 -0
  60. package/src/handlers/input/RemoveAllBindingsToolHandler.js +20 -0
  61. package/src/handlers/input/RemoveInputActionToolHandler.js +20 -0
  62. package/src/handlers/input/RemoveInputBindingToolHandler.js +20 -0
  63. package/src/handlers/input/TouchSimulationHandler.js +142 -0
  64. package/src/handlers/menu/ExecuteMenuItemToolHandler.js +304 -0
  65. package/src/handlers/package/PackageManagerToolHandler.js +248 -0
  66. package/src/handlers/package/RegistryConfigToolHandler.js +198 -0
  67. package/src/handlers/playmode/GetEditorStateToolHandler.js +81 -0
  68. package/src/handlers/playmode/PauseToolHandler.js +44 -0
  69. package/src/handlers/playmode/PlayToolHandler.js +91 -0
  70. package/src/handlers/playmode/StopToolHandler.js +77 -0
  71. package/src/handlers/playmode/WaitForEditorStateToolHandler.js +45 -0
  72. package/src/handlers/scene/CreateSceneToolHandler.js +91 -0
  73. package/src/handlers/scene/GetSceneInfoToolHandler.js +20 -0
  74. package/src/handlers/scene/ListScenesToolHandler.js +58 -0
  75. package/src/handlers/scene/LoadSceneToolHandler.js +92 -0
  76. package/src/handlers/scene/SaveSceneToolHandler.js +76 -0
  77. package/src/handlers/screenshot/AnalyzeScreenshotToolHandler.js +238 -0
  78. package/src/handlers/screenshot/CaptureScreenshotToolHandler.js +692 -0
  79. package/src/handlers/script/BuildCodeIndexToolHandler.js +163 -0
  80. package/src/handlers/script/ScriptCreateClassFileToolHandler.js +60 -0
  81. package/src/handlers/script/ScriptEditStructuredToolHandler.js +173 -0
  82. package/src/handlers/script/ScriptIndexStatusToolHandler.js +61 -0
  83. package/src/handlers/script/ScriptPackagesListToolHandler.js +103 -0
  84. package/src/handlers/script/ScriptReadToolHandler.js +106 -0
  85. package/src/handlers/script/ScriptRefactorRenameToolHandler.js +83 -0
  86. package/src/handlers/script/ScriptRefsFindToolHandler.js +144 -0
  87. package/src/handlers/script/ScriptRemoveSymbolToolHandler.js +79 -0
  88. package/src/handlers/script/ScriptSearchToolHandler.js +320 -0
  89. package/src/handlers/script/ScriptSymbolFindToolHandler.js +117 -0
  90. package/src/handlers/script/ScriptSymbolsGetToolHandler.js +96 -0
  91. package/src/handlers/settings/GetProjectSettingsToolHandler.js +161 -0
  92. package/src/handlers/settings/UpdateProjectSettingsToolHandler.js +272 -0
  93. package/src/handlers/system/GetCommandStatsToolHandler.js +25 -0
  94. package/src/handlers/system/PingToolHandler.js +53 -0
  95. package/src/handlers/system/RefreshAssetsToolHandler.js +45 -0
  96. package/src/handlers/ui/ClickUIElementToolHandler.js +110 -0
  97. package/src/handlers/ui/FindUIElementsToolHandler.js +63 -0
  98. package/src/handlers/ui/GetUIElementStateToolHandler.js +50 -0
  99. package/src/handlers/ui/SetUIElementValueToolHandler.js +49 -0
  100. package/src/handlers/ui/SimulateUIInputToolHandler.js +156 -0
  101. package/src/handlers/video/CaptureVideoForToolHandler.js +96 -0
  102. package/src/handlers/video/CaptureVideoStartToolHandler.js +38 -0
  103. package/src/handlers/video/CaptureVideoStatusToolHandler.js +30 -0
  104. package/src/handlers/video/CaptureVideoStopToolHandler.js +32 -0
  105. package/src/lsp/CSharpLspUtils.js +134 -0
  106. package/src/lsp/LspProcessManager.js +60 -0
  107. package/src/lsp/LspRpcClient.js +133 -0
  108. package/src/tools/analysis/analyzeSceneContents.js +100 -0
  109. package/src/tools/analysis/findByComponent.js +87 -0
  110. package/src/tools/analysis/getAnimatorState.js +326 -0
  111. package/src/tools/analysis/getComponentValues.js +182 -0
  112. package/src/tools/analysis/getGameObjectDetails.js +159 -0
  113. package/src/tools/analysis/getInputActionsState.js +329 -0
  114. package/src/tools/analysis/getObjectReferences.js +86 -0
  115. package/src/tools/input/inputActionsEditor.js +556 -0
  116. package/src/tools/scene/createScene.js +112 -0
  117. package/src/tools/scene/getSceneInfo.js +95 -0
  118. package/src/tools/scene/listScenes.js +82 -0
  119. package/src/tools/scene/loadScene.js +122 -0
  120. package/src/tools/scene/saveScene.js +91 -0
  121. package/src/tools/system/ping.js +72 -0
  122. package/src/tools/video/recordFor.js +31 -0
  123. package/src/tools/video/recordPlayMode.js +61 -0
  124. package/src/utils/csharpParse.js +88 -0
  125. package/src/utils/validators.js +90 -0
@@ -0,0 +1,101 @@
1
+ import { BaseToolHandler } from '../base/BaseToolHandler.js';
2
+
3
+ /**
4
+ * Handler for the delete_gameobject tool
5
+ * Deletes GameObjects from the Unity scene
6
+ */
7
+ export class DeleteGameObjectToolHandler extends BaseToolHandler {
8
+ constructor(unityConnection) {
9
+ super(
10
+ 'delete_gameobject',
11
+ 'Delete GameObject(s) by path or paths (optionally include children).',
12
+ {
13
+ type: 'object',
14
+ properties: {
15
+ path: {
16
+ type: 'string',
17
+ description: 'Path to a single GameObject to delete'
18
+ },
19
+ paths: {
20
+ type: 'array',
21
+ description: 'Array of paths to multiple GameObjects to delete',
22
+ items: {
23
+ type: 'string'
24
+ }
25
+ },
26
+ includeChildren: {
27
+ type: 'boolean',
28
+ description: 'Whether to delete children (default: true)'
29
+ }
30
+ },
31
+ required: []
32
+ }
33
+ );
34
+
35
+ this.unityConnection = unityConnection;
36
+ }
37
+
38
+ /**
39
+ * Validates the input parameters
40
+ * @param {object} params - Input parameters
41
+ * @throws {Error} If validation fails
42
+ */
43
+ validate(params) {
44
+ super.validate(params);
45
+
46
+ // Either path or paths must be provided
47
+ if (!params.path && (!params.paths || params.paths.length === 0)) {
48
+ throw new Error('Either "path" or "paths" parameter must be provided');
49
+ }
50
+
51
+ // Validate paths array if provided
52
+ if (params.paths) {
53
+ if (!Array.isArray(params.paths)) {
54
+ throw new Error('paths must be an array of strings');
55
+ }
56
+
57
+ for (const path of params.paths) {
58
+ if (typeof path !== 'string') {
59
+ throw new Error('All paths must be strings');
60
+ }
61
+ }
62
+ }
63
+ }
64
+
65
+ /**
66
+ * Executes the delete_gameobject command
67
+ * @param {object} params - Input parameters
68
+ * @returns {Promise<object>} Deletion result
69
+ */
70
+ async execute(params) {
71
+ // Ensure connected
72
+ if (!this.unityConnection.isConnected()) {
73
+ await this.unityConnection.connect();
74
+ }
75
+
76
+ // Send delete_gameobject command
77
+ const result = await this.unityConnection.sendCommand('delete_gameobject', params);
78
+
79
+ // Check for errors from Unity
80
+ if (result.error) {
81
+ throw new Error(result.error);
82
+ }
83
+
84
+ // Add summary
85
+ if (result.deletedCount !== undefined) {
86
+ if (result.deletedCount === 0) {
87
+ result.summary = 'No GameObjects were deleted';
88
+ } else if (result.deletedCount === 1) {
89
+ result.summary = `Deleted 1 GameObject: ${result.deleted[0]}`;
90
+ } else {
91
+ result.summary = `Deleted ${result.deletedCount} GameObjects`;
92
+ }
93
+
94
+ if (result.notFoundCount > 0) {
95
+ result.summary += ` (${result.notFoundCount} not found)`;
96
+ }
97
+ }
98
+
99
+ return result;
100
+ }
101
+ }
@@ -0,0 +1,119 @@
1
+ import { BaseToolHandler } from '../base/BaseToolHandler.js';
2
+
3
+ /**
4
+ * Handler for the find_gameobject tool
5
+ * Finds GameObjects in Unity scene by various criteria
6
+ */
7
+ export class FindGameObjectToolHandler extends BaseToolHandler {
8
+ constructor(unityConnection) {
9
+ super(
10
+ 'find_gameobject',
11
+ 'Find GameObjects by name, tag, or layer with optional exact matching.',
12
+ {
13
+ type: 'object',
14
+ properties: {
15
+ name: {
16
+ type: 'string',
17
+ description: 'Name to search for'
18
+ },
19
+ tag: {
20
+ type: 'string',
21
+ description: 'Tag to search for'
22
+ },
23
+ layer: {
24
+ type: 'number',
25
+ description: 'Layer index to search for (0-31)',
26
+ minimum: 0,
27
+ maximum: 31
28
+ },
29
+ exactMatch: {
30
+ type: 'boolean',
31
+ description: 'Whether to match name exactly (default: false)'
32
+ }
33
+ },
34
+ required: []
35
+ }
36
+ );
37
+
38
+ this.unityConnection = unityConnection;
39
+ }
40
+
41
+ /**
42
+ * Validates the input parameters
43
+ * @param {object} params - Input parameters
44
+ * @throws {Error} If validation fails
45
+ */
46
+ validate(params) {
47
+ super.validate(params);
48
+
49
+ // At least one search criteria must be provided
50
+ if (!params.name && !params.tag && params.layer === undefined) {
51
+ throw new Error('At least one search criteria (name, tag, or layer) must be provided');
52
+ }
53
+
54
+ // Validate layer
55
+ if (params.layer !== undefined) {
56
+ const layer = Number(params.layer);
57
+ if (isNaN(layer) || layer < 0 || layer > 31) {
58
+ throw new Error('layer must be a number between 0 and 31');
59
+ }
60
+ }
61
+ }
62
+
63
+ /**
64
+ * Executes the find_gameobject command
65
+ * @param {object} params - Input parameters
66
+ * @returns {Promise<object>} Found GameObjects
67
+ */
68
+ async execute(params) {
69
+ // Ensure connected
70
+ if (!this.unityConnection.isConnected()) {
71
+ await this.unityConnection.connect();
72
+ }
73
+
74
+ // Send find_gameobject command
75
+ const result = await this.unityConnection.sendCommand('find_gameobject', params);
76
+
77
+ // Check for errors from Unity
78
+ if (result.error) {
79
+ throw new Error(result.error);
80
+ }
81
+
82
+ // Add summary information
83
+ if (result.objects && Array.isArray(result.objects)) {
84
+ result.summary = this.generateSummary(result.objects, params);
85
+ }
86
+
87
+ return result;
88
+ }
89
+
90
+ /**
91
+ * Generates a summary of the search results
92
+ * @param {Array} objects - Found GameObjects
93
+ * @param {object} searchParams - Search parameters used
94
+ * @returns {string} Summary text
95
+ */
96
+ generateSummary(objects, searchParams) {
97
+ const parts = [];
98
+
99
+ if (searchParams.name) {
100
+ parts.push(`name${searchParams.exactMatch === false ? ' containing' : ''} "${searchParams.name}"`);
101
+ }
102
+ if (searchParams.tag) {
103
+ parts.push(`tag "${searchParams.tag}"`);
104
+ }
105
+ if (searchParams.layer !== undefined) {
106
+ parts.push(`layer ${searchParams.layer}`);
107
+ }
108
+
109
+ const criteria = parts.join(', ');
110
+
111
+ if (objects.length === 0) {
112
+ return `No GameObjects found matching ${criteria}`;
113
+ } else if (objects.length === 1) {
114
+ return `Found 1 GameObject matching ${criteria}: ${objects[0].name}`;
115
+ } else {
116
+ return `Found ${objects.length} GameObjects matching ${criteria}`;
117
+ }
118
+ }
119
+ }
@@ -0,0 +1,132 @@
1
+ import { BaseToolHandler } from '../base/BaseToolHandler.js';
2
+
3
+ /**
4
+ * Handler for the get_hierarchy tool
5
+ * Gets the Unity scene hierarchy
6
+ */
7
+ export class GetHierarchyToolHandler extends BaseToolHandler {
8
+ constructor(unityConnection) {
9
+ super(
10
+ 'get_hierarchy',
11
+ 'Get scene hierarchy. For large scenes, prefer nameOnly=true. With nameOnly, use maxObjects ~100–500; when requesting details, keep maxObjects ~10–50 to conserve tokens. Only enable includeComponents/includeTransform when necessary.',
12
+ {
13
+ type: 'object',
14
+ properties: {
15
+ rootPath: {
16
+ type: 'string',
17
+ description: 'Path to GameObject whose children will be the root of the returned hierarchy (e.g., "/Team_0" returns Team_0\'s children). If not specified, returns scene root objects.'
18
+ },
19
+ includeInactive: {
20
+ type: 'boolean',
21
+ description: 'Include inactive GameObjects (default: true)'
22
+ },
23
+ maxDepth: {
24
+ type: 'number',
25
+ description: 'Maximum depth to traverse from the root. 0=immediate children only (default), 1=children+grandchildren, 2=children+grandchildren+great-grandchildren, etc. (-1 for unlimited)',
26
+ minimum: -1
27
+ },
28
+ includeComponents: {
29
+ type: 'boolean',
30
+ description: 'Include component information (default: false). WARNING: Significantly increases response size - use with small maxObjects values.'
31
+ },
32
+ includeTransform: {
33
+ type: 'boolean',
34
+ description: 'Include transform information (default: false). WARNING: Increases response size - use with small maxObjects values.'
35
+ },
36
+ includeTags: {
37
+ type: 'boolean',
38
+ description: 'Include tag information (default: false)'
39
+ },
40
+ includeLayers: {
41
+ type: 'boolean',
42
+ description: 'Include layer information (default: false)'
43
+ },
44
+ nameOnly: {
45
+ type: 'boolean',
46
+ description: 'Return only names and paths for minimal data size (default: false). RECOMMENDED for large hierarchies to reduce token usage.'
47
+ },
48
+ maxObjects: {
49
+ type: 'number',
50
+ description: 'Maximum number of objects to include in response. Unity default: 100 (-1 for unlimited). RECOMMENDED: 10-50 for detailed info, 100-500 for nameOnly mode to avoid MCP token limits',
51
+ minimum: -1
52
+ }
53
+ },
54
+ required: []
55
+ }
56
+ );
57
+
58
+ this.unityConnection = unityConnection;
59
+ }
60
+
61
+ /**
62
+ * Validates the input parameters
63
+ * @param {object} params - Input parameters
64
+ * @throws {Error} If validation fails
65
+ */
66
+ validate(params) {
67
+ super.validate(params);
68
+
69
+ // Validate maxDepth
70
+ if (params.maxDepth !== undefined) {
71
+ const depth = Number(params.maxDepth);
72
+ if (isNaN(depth) || depth < -1) {
73
+ throw new Error('maxDepth must be -1 or a positive number');
74
+ }
75
+ }
76
+
77
+ // Validate maxObjects
78
+ if (params.maxObjects !== undefined) {
79
+ const maxObjects = Number(params.maxObjects);
80
+ if (isNaN(maxObjects) || maxObjects < -1) {
81
+ throw new Error('maxObjects must be -1 or a positive number');
82
+ }
83
+ }
84
+ }
85
+
86
+ /**
87
+ * Executes the get_hierarchy command
88
+ * @param {object} params - Input parameters
89
+ * @returns {Promise<object>} Scene hierarchy
90
+ */
91
+ async execute(params) {
92
+ // Ensure connected
93
+ if (!this.unityConnection.isConnected()) {
94
+ await this.unityConnection.connect();
95
+ }
96
+
97
+ // Send get_hierarchy command
98
+ const result = await this.unityConnection.sendCommand('get_hierarchy', params);
99
+
100
+ // Check for errors from Unity
101
+ if (result.error) {
102
+ throw new Error(result.error);
103
+ }
104
+
105
+ // Add helpful summary
106
+ if (result.hierarchy) {
107
+ result.totalObjects = this.countObjects(result.hierarchy);
108
+ result.summary = `Scene "${result.sceneName}" contains ${result.totalObjects} GameObject${result.totalObjects !== 1 ? 's' : ''} (${result.objectCount} at root level)`;
109
+ }
110
+
111
+ return result;
112
+ }
113
+
114
+ /**
115
+ * Counts total objects in hierarchy recursively
116
+ * @param {Array} hierarchy - Hierarchy array
117
+ * @returns {number} Total object count
118
+ */
119
+ countObjects(hierarchy) {
120
+ let count = 0;
121
+
122
+ for (const node of hierarchy) {
123
+ count++; // Count this node
124
+
125
+ if (node.children && Array.isArray(node.children)) {
126
+ count += this.countObjects(node.children);
127
+ }
128
+ }
129
+
130
+ return count;
131
+ }
132
+ }
@@ -0,0 +1,128 @@
1
+ import { BaseToolHandler } from '../base/BaseToolHandler.js';
2
+ import { validateVector3, validateLayer, validateGameObjectPath } from '../../utils/validators.js';
3
+
4
+ /**
5
+ * Handler for the modify_gameobject tool
6
+ * Modifies properties of existing GameObjects
7
+ */
8
+ export class ModifyGameObjectToolHandler extends BaseToolHandler {
9
+ constructor(unityConnection) {
10
+ super(
11
+ 'modify_gameobject',
12
+ 'Modify GameObject properties (transform/name/parent/active/tag/layer).',
13
+ {
14
+ type: 'object',
15
+ properties: {
16
+ path: {
17
+ type: 'string',
18
+ description: 'Path to the GameObject to modify (required)'
19
+ },
20
+ name: {
21
+ type: 'string',
22
+ description: 'New name for the GameObject'
23
+ },
24
+ position: {
25
+ type: 'object',
26
+ description: 'New world position',
27
+ properties: {
28
+ x: { type: 'number' },
29
+ y: { type: 'number' },
30
+ z: { type: 'number' }
31
+ }
32
+ },
33
+ rotation: {
34
+ type: 'object',
35
+ description: 'New rotation in Euler angles',
36
+ properties: {
37
+ x: { type: 'number' },
38
+ y: { type: 'number' },
39
+ z: { type: 'number' }
40
+ }
41
+ },
42
+ scale: {
43
+ type: 'object',
44
+ description: 'New local scale',
45
+ properties: {
46
+ x: { type: 'number' },
47
+ y: { type: 'number' },
48
+ z: { type: 'number' }
49
+ }
50
+ },
51
+ active: {
52
+ type: 'boolean',
53
+ description: 'Set active state'
54
+ },
55
+ parentPath: {
56
+ type: ['string', 'null'],
57
+ description: 'Path to new parent GameObject (null to unparent)'
58
+ },
59
+ tag: {
60
+ type: 'string',
61
+ description: 'New tag'
62
+ },
63
+ layer: {
64
+ type: 'number',
65
+ description: 'New layer index (0-31)',
66
+ minimum: 0,
67
+ maximum: 31
68
+ }
69
+ },
70
+ required: ['path']
71
+ }
72
+ );
73
+
74
+ this.unityConnection = unityConnection;
75
+ }
76
+
77
+ /**
78
+ * Validates the input parameters
79
+ * @param {object} params - Input parameters
80
+ * @throws {Error} If validation fails
81
+ */
82
+ validate(params) {
83
+ super.validate(params);
84
+
85
+ // Path is required
86
+ validateGameObjectPath(params.path);
87
+
88
+ // At least one modification must be specified
89
+ const modifiableProps = ['name', 'position', 'rotation', 'scale', 'active', 'parentPath', 'tag', 'layer'];
90
+ const hasModification = modifiableProps.some(prop => params.hasOwnProperty(prop));
91
+
92
+ if (!hasModification) {
93
+ throw new Error('At least one property to modify must be specified');
94
+ }
95
+
96
+ // Validate vector3 properties
97
+ if (params.position) validateVector3(params.position, 'position');
98
+ if (params.rotation) validateVector3(params.rotation, 'rotation');
99
+ if (params.scale) validateVector3(params.scale, 'scale');
100
+
101
+ // Validate layer
102
+ if (params.layer !== undefined) {
103
+ validateLayer(Number(params.layer));
104
+ }
105
+ }
106
+
107
+ /**
108
+ * Executes the modify_gameobject command
109
+ * @param {object} params - Input parameters
110
+ * @returns {Promise<object>} Modified GameObject info
111
+ */
112
+ async execute(params) {
113
+ // Ensure connected
114
+ if (!this.unityConnection.isConnected()) {
115
+ await this.unityConnection.connect();
116
+ }
117
+
118
+ // Send modify_gameobject command
119
+ const result = await this.unityConnection.sendCommand('modify_gameobject', params);
120
+
121
+ // Check for errors from Unity
122
+ if (result.error) {
123
+ throw new Error(result.error);
124
+ }
125
+
126
+ return result;
127
+ }
128
+ }