Unity中无法绘制火箭飞行轨迹的问题排查求助
问题:Unity太空模拟游戏轨迹绘制失效,Ghost火箭不移动
我正在开发一款太空模拟游戏,火箭需要借助引力在行星间航行。目前想要绘制火箭的飞行轨迹辅助玩家,用Unity的Simulate功能写了代码,但没法正常工作。游戏本身运行没问题,但用来绘制轨迹的ghost物体完全不动,一直停留在玩家火箭下方。
编辑补充:我发现哪怕执行ghostRocketRb.position = gameObject.GetComponent<Rigidbody2D>().position;,对ghostRocket的Rigidbody2D做的任何修改都不生效。
相关代码
TrajectoryVisualization.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.SceneManager; public class TrajectoryVisualization : MonoBehaviour { private static Scene TrajectoryScene; private static PhysicsScene TrajectoryPhysicsScene; private static LineRenderer lineRenderer; private static GameObject ghostRocketObj; private static List<GameObject> ghostPlanetsObj; private static List<GameObject> ghostBoundariesObj; [SerializeField] private static int simulationSteps = 50; void Start() { TrajectoryScene = SceneManager.CreateScene("TrajectorySimulation", new CreateSceneParameters(LocalPhysicsMode.Physics2D)); TrajectoryPhysicsScene = TrajectoryScene.GetPhysicsScene(); lineRenderer = GetComponent<LineRenderer>(); addPlanetsToSimulation(); addRocketToSimulation(); addBoundariesToSimulation(); } // Update is called once per frame void Update() { Physics.autoSimulation = false; Debug.Log("START SIMULATION"); ghostRocketObj.transform.position = gameObject.transform.position; Rigidbody2D ghostVelocity = ghostRocketObj.GetComponent<Rigidbody2D>(); ghostVelocity.velocity = gameObject.GetComponent<Rigidbody2D>().velocity; List<Vector3> pathPoints = new List<Vector3>(); for (int i = 0; i < simulationSteps; i++) { Gravity.calculateGravity(ghostPlanetsObj, ghostRocketObj.GetComponent<Rigidbody2D>(), true); TrajectoryPhysicsScene.Simulate(Time.fixedDeltaTime); pathPoints.Add(ghostRocketObj.transform.position); } lineRenderer.positionCount = simulationSteps; lineRenderer.SetPositions(pathPoints.ToArray()); Debug.Log("END SIMULATION"); Physics.autoSimulation = true; } private void addPlanetsToSimulation() { ghostPlanetsObj = new List<GameObject>(); //Add planets to simulation scene foreach (GameObject planet in ListPlanets.getPlanetsObject()) { GameObject ghostplanetObj = Instantiate(planet, planet.transform.position, planet.transform.rotation); ghostplanetObj.GetComponent<Renderer>().enabled = false; SceneManager.MoveGameObjectToScene(ghostplanetObj, TrajectoryScene); ghostPlanetsObj.Add(ghostplanetObj); } } private void addRocketToSimulation() { //Add planets to simulation scene ghostRocketObj = Instantiate(gameObject, gameObject.transform.position, gameObject.transform.rotation); ghostRocketObj.tag = "RocketSimulation"; ghostRocketObj.GetComponent<Renderer>().enabled = false; ghostRocketObj.GetComponent<Animator>().enabled = false; ghostRocketObj.GetComponent<Rotation>().enabled = false; ghostRocketObj.GetComponent<RocketThrust>().enabled = false; ghostRocketObj.GetComponent<PlayerInput>().enabled = false; ghostRocketObj.GetComponent<TrajectoryVisualization>().enabled = false; ghostRocketObj.GetComponent<AudioSource>().enabled = false; ghostRocketObj.GetComponent<Position>().enabled = false; SceneManager.MoveGameObjectToScene(ghostRocketObj, TrajectoryScene); } private void addBoundariesToSimulation() { ghostBoundariesObj = new List<GameObject>(); foreach (GameObject boundary in GameObject.FindGameObjectsWithTag("Boundary")) { GameObject ghostBoundaryObj = Instantiate(boundary, boundary.transform.position, boundary.transform.rotation); ghostBoundaryObj.GetComponent<Renderer>().enabled = false; SceneManager.MoveGameObjectToScene(ghostBoundaryObj, TrajectoryScene); ghostBoundariesObj.Add(ghostBoundaryObj); } } public static void createNewPlanetSimulation(GameObject newPlanet) { GameObject ghostplanetObj = Instantiate(newPlanet, newPlanet.transform.position, newPlanet.transform.rotation); ghostplanetObj.GetComponent<Renderer>().enabled = false; SceneManager.MoveGameObjectToScene(ghostplanetObj, TrajectoryScene); ghostPlanetsObj.Add(ghostplanetObj); } }
Gravity.cs
using System.Collections.Generic; using UnityEngine; public class Gravity : MonoBehaviour { private static Rigidbody2D planetAttractor; [SerializeField] private static float G = 4.0f; [SerializeField] private Rigidbody2D rocketPlayer; [SerializeField] private Rigidbody2D planetOrigin; // Start is called before the first frame update void Start() { planetAttractor = planetOrigin; Scoring.reference = planetOrigin.name; } void FixedUpdate() { calculateGravity(ListPlanets.getPlanetsObject(), rocketPlayer, false); } public static void calculateGravity(List<GameObject> planets, Rigidbody2D rocket, bool isSimulation) { float smallestDistance = Vector2.Distance(planets[0].GetComponent<Rigidbody2D>().position, rocket.position); foreach (GameObject planet in planets) { Rigidbody2D tmpBody = planet.GetComponent<Rigidbody2D>(); float distance = Vector2.Distance(tmpBody.position, rocket.position); if (distance <= smallestDistance) { planetAttractor = tmpBody; smallestDistance = distance; } } float massProduct = planetAttractor.mass*rocket.mass*G; Vector2 direction = planetAttractor.position - rocket.position; float distanceBetween = direction.magnitude; float unScaledforceMagnitude = massProduct/Mathf.Pow(distanceBetween,2); float forceMagnitude = G*unScaledforceMagnitude; Vector2 forceDirection = direction.normalized; Vector2 forceVector = forceDirection*forceMagnitude; Debug.Log("forceDirection: " + forceDirection); Debug.Log("forceMagnitude: " + forceMagnitude); Debug.Log("rocket.position: " + rocket.position); Debug.Log("rocket.velocity: " + rocket.velocity); rocket.AddForce(forceVector); } }
问题排查与解决
1. 修正Rigidbody2D状态同步方式
直接修改transform.position无法正确同步独立物理场景中Rigidbody2D的状态,必须操作Rigidbody2D自身的属性:
// 替换原状态同步代码 Rigidbody2D ghostRb = ghostRocketObj.GetComponent<Rigidbody2D>(); ghostRb.position = gameObject.GetComponent<Rigidbody2D>().position; ghostRb.velocity = gameObject.GetComponent<Rigidbody2D>().velocity; ghostRb.angularVelocity = 0f; ghostRb.ResetForces(); // 清除残留受力,避免模拟偏差
2. 修正物理模拟控制API
你创建的是2D物理场景,应该使用Physics2D.autoSimulation而非Physics.autoSimulation:
// 替换原代码中的Physics.autoSimulation Physics2D.autoSimulation = false; // ... 模拟逻辑 ... Physics2D.autoSimulation = true;
3. 修复引力计算的公式错误
代码中重复乘以引力常数G,导致引力被平方放大,修正为标准万有引力公式:
// 替换Gravity.cs中的力计算部分 float forceMagnitude = (G * planetAttractor.mass * rocket.mass) / Mathf.Pow(distanceBetween, 2); Vector2 forceDirection = direction.normalized; Vector2 forceVector = forceDirection * forceMagnitude;
4. 移除静态变量的全局污染
TrajectoryVisualization中的静态变量(如ghostPlanetsObj)会导致多实例/场景切换时的状态冲突,建议改为非静态变量:
// 替换原静态变量定义 private Scene TrajectoryScene; private PhysicsScene TrajectoryPhysicsScene; private LineRenderer lineRenderer; private GameObject ghostRocketObj; private List<GameObject> ghostPlanetsObj; private List<GameObject> ghostBoundariesObj; [SerializeField] private int simulationSteps = 50;
内容的提问来源于stack exchange,提问作者CromSoldier
相关产品推荐
相关产品推荐

