using System.Collections.Generic; using MCPForUnity.Editor.Helpers; using Newtonsoft.Json.Linq; using UnityEngine; using MCPForUnity.Runtime.Helpers; namespace MCPForUnity.Editor.Tools.Physics { internal static class PhysicsSimulationOps { public static object SimulateStep(JObject @params) { var p = new ToolParams(@params); string dimension = (p.Get("dimension") ?? "3d").ToLowerInvariant(); int steps = Mathf.Clamp(p.GetInt("steps") ?? 1, 1, 100); float stepSize = p.GetFloat("step_size") ?? Time.fixedDeltaTime; string targetStr = p.Get("target"); string searchMethod = p.Get("search_method"); if (dimension != "3d" && dimension != "2d") return new ErrorResponse($"Invalid dimension: '{dimension}'. Use '3d' or '2d'."); if (dimension == "2d") { Physics2D.SyncTransforms(); for (int i = 0; i < steps; i++) Physics2D.Simulate(stepSize); } else { UnityEngine.Physics.SyncTransforms(); var prevMode = UnityPhysicsCompat.GetPhysicsSimulationMode(); if (prevMode != UnityPhysicsCompat.SimulationMode.Script) UnityPhysicsCompat.TrySetPhysicsSimulationMode(UnityPhysicsCompat.SimulationMode.Script); try { for (int i = 0; i < steps; i++) UnityEngine.Physics.Simulate(stepSize); } finally { if (prevMode != UnityPhysicsCompat.SimulationMode.Unknown && prevMode != UnityPhysicsCompat.SimulationMode.Script) { UnityPhysicsCompat.TrySetPhysicsSimulationMode(prevMode); } } } // Collect rigidbody states after simulation List rigidbodies; if (!string.IsNullOrEmpty(targetStr)) { rigidbodies = CollectTargetRigidbody(targetStr, searchMethod, dimension); } else { rigidbodies = CollectActiveRigidbodies(dimension); } return new { success = true, message = $"Executed {steps} physics step(s) ({dimension.ToUpper()}, step_size={stepSize:F4}s).", data = new { steps_executed = steps, step_size = stepSize, dimension, rigidbodies } }; } private static List CollectTargetRigidbody(string targetStr, string searchMethod, string dimension) { var results = new List(); var go = GameObjectLookup.FindByTarget(JToken.FromObject(targetStr), searchMethod ?? "by_name"); if (go == null) return results; if (dimension == "2d") { var rb2d = go.GetComponent(); if (rb2d != null) { results.Add(new { name = go.name, instanceID = go.GetInstanceIDCompat(), position = new[] { rb2d.position.x, rb2d.position.y }, #if UNITY_6000_0_OR_NEWER velocity = new[] { rb2d.linearVelocity.x, rb2d.linearVelocity.y }, #else velocity = new[] { rb2d.velocity.x, rb2d.velocity.y }, #endif angularVelocity = rb2d.angularVelocity }); } } else { var rb = go.GetComponent(); if (rb != null) { results.Add(new { name = go.name, instanceID = go.GetInstanceIDCompat(), position = new[] { rb.position.x, rb.position.y, rb.position.z }, #if UNITY_6000_0_OR_NEWER velocity = new[] { rb.linearVelocity.x, rb.linearVelocity.y, rb.linearVelocity.z }, #else velocity = new[] { rb.velocity.x, rb.velocity.y, rb.velocity.z }, #endif angularVelocity = new[] { rb.angularVelocity.x, rb.angularVelocity.y, rb.angularVelocity.z } }); } } return results; } private static List CollectActiveRigidbodies(string dimension) { var results = new List(); const int maxResults = 50; if (dimension == "2d") { var allRb2d = UnityFindObjectsCompat.FindAll(); foreach (var rb2d in allRb2d) { if (results.Count >= maxResults) break; if (rb2d.bodyType == RigidbodyType2D.Static) continue; if (rb2d.IsSleeping()) continue; results.Add(new { name = rb2d.gameObject.name, instanceID = rb2d.gameObject.GetInstanceIDCompat(), position = new[] { rb2d.position.x, rb2d.position.y }, #if UNITY_6000_0_OR_NEWER velocity = new[] { rb2d.linearVelocity.x, rb2d.linearVelocity.y }, #else velocity = new[] { rb2d.velocity.x, rb2d.velocity.y }, #endif angularVelocity = rb2d.angularVelocity }); } } else { var allRb = UnityFindObjectsCompat.FindAll(); foreach (var rb in allRb) { if (results.Count >= maxResults) break; if (rb.isKinematic) continue; if (rb.IsSleeping()) continue; results.Add(new { name = rb.gameObject.name, instanceID = rb.gameObject.GetInstanceIDCompat(), position = new[] { rb.position.x, rb.position.y, rb.position.z }, #if UNITY_6000_0_OR_NEWER velocity = new[] { rb.linearVelocity.x, rb.linearVelocity.y, rb.linearVelocity.z }, #else velocity = new[] { rb.velocity.x, rb.velocity.y, rb.velocity.z }, #endif angularVelocity = new[] { rb.angularVelocity.x, rb.angularVelocity.y, rb.angularVelocity.z } }); } } return results; } } }