2

所以我正在尝试制作一个程序,允许一个领域中的小行星像这样相互吸引: https ://www.youtube.com/watch?v=iAWZwTWJmhM

我有两个程序可以做到这一点,一个随机生成小行星,另一个对每个物体施加引力。问题是小行星会随着它们越来越近而变得更快,直到它们达到子弹速度,并且施加的力使它们彼此远离并消失。有没有办法让他们在接触时抵消他们的力量。我尝试了 Rigidbody.isKinematic 但这使得小行星静止而不是像在太空中那样旋转。生病发布下面的代码,但这是我使用代码的两个项目。 https://www.youtube.com/watch?v=Ouu3D_VHx9o https://www.youtube.com/watch?v=6rTfZ2ox2_g

小行星产卵器的代码。我在随机比例生成器中添加了:

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

public class AsteroidFieldGenerator : MonoBehaviour
{
public Transform AsteroidPrefab;
public int fieldRadius = 50;
public int asteroidCount = 60;
public float SizeMinPercent = 1;
public float SizeMaxPercent = 100;
// Start is called before the first frame update
void Start()
{
    for (int loop = 0; loop < asteroidCount; loop++)
    {
        Instantiate(AsteroidPrefab, Random.insideUnitSphere * fieldRadius, Quaternion.identity);
        AsteroidPrefab.transform.localScale = Vector3.one * (Random.Range(SizeMinPercent, SizeMaxPercent) / 100);
    }

}

// Update is called once per frame
void Update()
{

}
}

应用重力程序:

'''

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

public class Attractor : MonoBehaviour
{

const float G = 667.4f;

public static List<Attractor> Attractors;

public Rigidbody rb;

void FixedUpdate()
{
    foreach (Attractor attractor in Attractors)
    {
        if (attractor != this)
            Attract(attractor);
    }
}

void OnEnable()
{
    if (Attractors == null)
        Attractors = new List<Attractor>();

    Attractors.Add(this);
}

void OnDisable()
{
    Attractors.Remove(this);
}

void Attract(Attractor objToAttract)
{
    Rigidbody rbToAttract = objToAttract.rb;

    Vector3 direction = rb.position - rbToAttract.position;
    float distance = direction.magnitude;

    if (distance == 0f)

        return;

    float forceMagnitude = G * (rb.mass * rbToAttract.mass) / Mathf.Pow(distance, 2);
    Vector3 force = direction.normalized * forceMagnitude;

    if (distance == 0)
        force = force * 0;

    rbToAttract.AddForce(force);

}

}

'''

4

1 回答 1

0

您必须施加阻尼(阻力)力,类似于大气阻力(空气阻力)。然后系统的总能量会降低,这使得粒子更有可能聚集在一起。所以基本上,运动方程应该是这样的

F_grv[i,j,:] = G*mj*mi * (x[j,:] - x[i,:]) / norm(x[i,:] - x[j,:])^3 
F_res[i,j,:] = - R( norm(x[i,:] - x[j,:]) ) * norm(v[i,:])^a * v[i,:] 

R(u) = non-negative function that rapidly decreases when u goes away from 0, 
       and increasing rapidly when u gets very close to 0.
a is some positive number, say 1 or 2 or more. 

dx[i,:]/dt = v[i,:]
dv[i,:]/dt = (1/mi) * sum(F_grv[i,j,:] + F_res[i,j] for j=1:n)

这是一个 matlab 代码,用于一个粒子绕重心运行,标准牛顿引力作用在它上面加上一个速度相关的阻尼力:

function gravity_damping()
    t = 0;
    x0 = [5;1];
    x_start = [-1; 10];
    v_start = [0.15; 0.];
    x = x_start;
    v = v_start;
    h = 0.3;
    n = 700;
    k0 = 7;
    lambda = 2;
    power1 = 10;
    power2 = 2;
    hold on
    grid on
    axis([-7 8 -3 12])
    plot(x0(1), x0(2), 'ro');
    for k = 1:n
        t = t+h;
        x = x + h*v/2;
        v = v + h*F_grv(x-x0, 1, 1) + h*F_res(x-x0, v, k0, lambda, power1, power2);
        x = x + h*v/2;
        plot(x(1), x(2), 'bo');
        pause(0.1)
    end
end

function  dvdt = F_grv(x_x0, mass, gr_const)
    dvdt = - gr_const * mass * (x_x0) / norm(x_x0)^3;
end

function  dvdt = F_res(x_x0, v, k0, a, power1, power2)
    dvdt = - (k_res(norm(x_x0), k0, a, power1) * norm(v)^power2) * v;
end

function coeff = k_res(u, k0, a, power)
    coeff = k0/(1 + (a*u)^(power));
end

于 2020-05-28T02:57:51.147 回答