在Unity中使用牛顿物理学模拟行星的轨迹

问题描述

我正在使用牛顿物理学对恒星系统进行仿真。系统中的行星相互吸引,引力有点逼真。但是,我想计算一个行星的未来轨迹。用户应该在模拟中选择一个行星并为其提供初始速度。然后将使用此初始速度和来自其他行星的引力来计算轨迹。我的方法是尝试在运行轨迹计算的地方创建一个平行的物理场景。基本上,我实例化了从主场景到并行场景的所有对象,并在并行场景中运行物理引擎。然后,我使用LineRenderer绘制轨迹,使用并行对象的位置更新此停留时间。但这不起作用。绘制的线都是直的,不会像预期的那样弯曲。即使我将初始速度设置为0 ...,主对象也由于某种原因而获得了速度提升。

我可以不提起我一直在遵循这些教程,但没有成功: https://www.youtube.com/watch?v=GLu1T5Y2SSc https://www.codinblack.com/visualizing-the-trajectory-of-a-bouncing-object-in-unity3d/

这是我的重力脚本:

using System.Collections.Generic;
using UnityEngine;

public class Attractor : MonoBehavIoUr
{
    public Rigidbody rigidBody;
    public const float gravityConstant = 667.408f;

    public bool staticBody = false;
    
    public static List<Attractor> Attractors;
     

    // Update call for the attractor. Runs through the static attractors list.
    void Start(){
        if (staticBody)
           { rigidBody.isKinematic = true;
            }  

    }

    void FixedUpdate(){
        SimulateStellarsystem();
    }

    // For adding attractors to the attractors list
    void OnEnable(){  
        if(Attractors == null){
            Attractors = new List<Attractor>();
        }
        Attractors.Add(this);
    }

    // For removing attractors from the attractors list
    void Ondisable(){
        Attractors.Remove(this);
    }

    void Attract(Attractor attractedobj){
        
        Rigidbody rigidBodyToAttract = attractedobj.rigidBody;
        Vector3 distanceDirection = rigidBody.position - rigidBodyToAttract.position;
        float distance = distanceDirection.magnitude;
        //If two attractors are at the exact same place we just return out of it
        if(distance == 0f){
            return;
        }
        float forceMag = (gravityConstant * rigidBody.mass * rigidBodyToAttract.mass) / Mathf.Pow(distance,2);
        Vector3 forceDirection = distanceDirection.normalized * forceMag;

        rigidBodyToAttract.AddForce(forceDirection);
  }

  public void SimulateStellarsystem(){
      if(Attractors != null){
        foreach(Attractor attractor in Attractors){
                if ((attractor != this) && (attractor.gameObject.scene == this.gameObject.scene)&&(!attractor.staticBody)){
                    Attract(attractor);
                }
            }
    }
  }

}

还有我用于模拟轨迹的脚本。现在,我已经硬编码了一些要复制到并行场景中的对象。

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class MotionSimv2: MonoBehavIoUr
{
    private Scene mainScene;
    private PhysicsScene mainPhysicsScene;
    private Scene parallelScene;
    private PhysicsScene parallelPhysicsScene;

    public Vector3 initalVeLocity;
    public GameObject mainObject;
    public GameObject plane;
    public GameObject sphere;
    public GameObject sphere2;
    private LineRenderer lineRenderer;

    private bool mainPhysics = true;

    void Start()
    {
        Physics.autoSimulation = false;
        lineRenderer = GetComponent<LineRenderer>();
        lineRenderer.positionCount = 1000;

        mainScene = SceneManager.GetActiveScene();
        mainPhysicsScene = mainScene.GetPhysicsScene();

        CreateSceneParameters createSceneParameters = new CreateSceneParameters(LocalPhysicsMode.Physics3D);
        parallelScene = SceneManager.CreateScene("ParallelScene",createSceneParameters);
        parallelPhysicsScene = parallelScene.GetPhysicsScene();

    }

    void Update()
    {
        if (Input.GetMouseButtonDown(0)){
            SimulatePhysics();
            mainPhysics = false;
        }

        if (Input.GetMouseButtonUp(0)){
            mainPhysics = true;
            Shoot();
        }
    }

    void FixedUpdate(){

        if (mainPhysics){
            mainScene.GetPhysicsScene().Simulate(Time.fixedDeltaTime);
            }
    }

    void SimulatePhysics()
    {
        SceneManager.SetActiveScene(parallelScene);
        
        GameObject simulationObject = Instantiate(mainObject);
        GameObject simulationPlane = Instantiate(plane);
        GameObject simulationSphere = Instantiate(sphere);
        GameObject simulationSphere2 = Instantiate(sphere2);

        simulationObject.GetComponent<Rigidbody>().veLocity = mainObject.GetComponent<Rigidbody>().veLocity + initalVeLocity;
        simulationObject.GetComponent<Rigidbody>().angularVeLocity = mainObject.GetComponent<Rigidbody>().angularVeLocity;

        simulationSphere.GetComponent<Rigidbody>().veLocity = sphere.GetComponent<Rigidbody>().veLocity;
        simulationSphere.GetComponent<Rigidbody>().angularVeLocity = sphere.GetComponent<Rigidbody>().angularVeLocity;

        simulationSphere2.GetComponent<Rigidbody>().veLocity = sphere2.GetComponent<Rigidbody>().veLocity;
        simulationSphere2.GetComponent<Rigidbody>().angularVeLocity = sphere2.GetComponent<Rigidbody>().angularVeLocity;

        for (int i = 0; i < lineRenderer.positionCount; i++)
        {
            parallelPhysicsScene.Simulate(Time.fixedDeltaTime);
            lineRenderer.SetPosition(i,simulationObject.transform.position);
        }

        Destroy(simulationObject);
        Destroy(simulationPlane);
        Destroy(simulationSphere2);
        Destroy(simulationSphere);

        SceneManager.SetActiveScene(mainScene);
    }

    void Shoot()
    {
        mainObject.GetComponent<Rigidbody>().veLocity += initalVeLocity;
    }

}

我是Unity新手,不胜感激!

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)