So I’m trying to recreate some python code I found on the interwebs in unity. I apologize in advance for my awful code, I’m self taught and probably have alot of bad habits, but here we go!
This is the python code I’m trying to recreate (which runs properly in python I checked)
https://fiftyexamples.readthedocs.io/en/latest/gravity.html
now I have my code split up between the data layer, and classes to display it in unity.
here is what I have:
Class 1: Body
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
public class Body {
public double mass;
public double vx;
public double vy;
public double px;
public double py;
public Body(double oMass, double oVx = 0, double oVy = 0, double oPx = 0, double oPy = 0){
mass = oMass;
vx = oVx;
vy = oVy;
px = oPx;
py = oPy;
}
public Force Attraction(Body other){
if (other == this)
{
Debug.Log ("cant check gravity on yourslef!");
return Force.Null();
}
double sx = this.px;
double sy = this.py;
double ox = other.px;
double oy = other.py;
double dx = (ox - sx);
double dy = (oy - sy);
double d = Math.Sqrt(Math.Pow(dx, 2) + Math.Pow(dy, 2));
if (d == 0) {
Debug.Log ("Collision!!");
return Force.Null();
}
double f = SSystem.G * this.mass * other.mass / Math.Pow(d, 2);
double theta = Math.Atan2 (dy, dx);
double fx = Math.Cos (theta) * f;
double fy = Math.Sin (theta) * f;
//Debug.Log ("fx test" + fx);
//Debug.Log("fy test" + fy);
Force force = new Force(fx, fy);
return force;
}
}
Class 2: SSystem
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
public class SSystem {
public static double G = 0.0000000000667428;
public static double AU = (149.6e6 * 1000) ;
public Dictionary<string, double> times = new Dictionary<string, double>(); // multiplyer for run speed
public int startBodies = 3;
private int step;
public string timestepKey = "days";
public double timestep;
public Body[] bodies = new Body[3];
Force[] force = new Force[3];
public SSystem()
{
Debug.Log (G);
Debug.Log (AU);
times.Add ("seconds", 1);
times.Add ("minutes", 60);
times.Add ("hours", 3600);
times.Add ("days", 86400);
times.Add ("months", 2592000);
Body sun = new Body(1.98892 * Math.Pow(10,30));
Body earth = new Body (5.9742 * Math.Pow (10, 24), 0f, 29.783 * 1000, -1 * AU, 0);
Body venus = new Body (4.8685 * Math.Pow (10, 24), 0f, -35.02 * 1000, 0.723 * AU, 0);
bodies[0] = sun;
bodies [1] = earth;
bodies [2] = venus;
for (int i = 0; i < force.Length; i++) {
force [i] = Force.Null ();
}
}
public void Update(float deltaTime)
{
if (!times.ContainsKey(timestepKey))
{
Debug.Log ("timestep key" + timestepKey + "doesnt exist in the dictionary");
return;
}
timestep = times[timestepKey] * deltaTime;
step = 0;
foreach (Body body1 in bodies)
{
foreach (Body body2 in bodies)
{
if (body1 == body2) {
continue;
}
Force thisForce = body1.Attraction (body2);
//Debug.Log ("this force x " + thisForce.Fx);
//Debug.Log ("this force y " + thisForce.Fy);
force[step] = force[step].AddForce (thisForce);
//Debug.Log ("this force x " + force[step].Fx);
//Debug.Log ("this force y " + force[step].Fy);
}
body1.vx += force [step].Fx / body1.mass * timestep;
body1.vy += force [step].Fy / body1.mass * timestep;
//Debug.Log ("body vx " + body.vx);
//Debug.Log ("body vy " + body.vy);
body1.px += body1.vx * timestep;
body1.py += body1.vy * timestep;
step++;
}
/*
step = 0;
foreach (Body body in bodies)
{
body.vx += force [step].Fx / body.mass * timestep;
body.vy += force [step].Fy / body.mass * timestep;
//Debug.Log ("body vx " + body.vx);
//Debug.Log ("body vy " + body.vy);
body.px += body.vx * timestep;
body.py += body.vy * timestep;
}
*/
}
}
Class 3: Force
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Force {
public double Fx;
public double Fy;
public Force(double fx, double fy)
{
Fx = fx;
Fy = fy;
}
public Force AddForce(Force other){
Force newForce = new Force (this.Fx + other.Fx, this.Fy + other.Fy);
return newForce;
}
public static Force Null()
{
Force force = new Force (0, 0);
return force;
}
}
thats it for the data layer, these next two are monobehaviours,
Class 1: Game (this one is placed on an empty object and linked to the prefab(which is just a sphere with the other class “GameBody” attached
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
public class Game : MonoBehaviour {
public SSystem sSystem;
public GameObject bodyPrefab;
private int index;
public List<GameObject> oBodies;
public double Scale = 250 / SSystem.AU ;
void Start () {
sSystem = new SSystem ();
index = 0;
foreach (Body body in sSystem.bodies)
{
oBodies.Add (Instantiate (bodyPrefab, new Vector3 ((float)body.px, (float)body.py), Quaternion.identity, this.transform));
oBodies [index].GetComponent<GameBody> ().initilize (index);
index++;
}
}
// Update is called once per frame
void Update () {
index = 0;
sSystem.Update(Time.deltaTime);
foreach (GameObject body in oBodies) {
body.GetComponent<GameBody>().update ((float)sSystem.bodies [index].px * (float)Scale, (float)sSystem.bodies [index].py * (float)Scale);
index++;
}
}
}
and the last bit for each game object
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GameBody : MonoBehaviour {
public Game game;
public int Index;
void start(){
game = GetComponent<Game> ();
}
public void initilize(int index){
Index = index;
}
public void update(float px, float py){
this.transform.position = new Vector3 (px, py);
}
void Update () {
//this.transform.position = new Vector3 (game.sSystem.bodies [Index].px / 1000, game.sSystem.bodies [Index].py / 1000);
}
}
Thanks in advance for the help, I’ve written it all tonight so there is probably a really obvious problem I’m missing.
Edit1: I guess I never really explained the problem, the planets are supposed to oribit the sun (which they do when you run the python code in python) but in unity they fall to the sun for a moment then blast off quite quickly. So im not sure if one of the math functions is failing to transfer properly or what…