// Calculates and returns the gravitational force between two physics objects this tick public Vector3 CalculateGravitationalForce(PhysicsObjectPair pair) { //Obtain Direction Vector Vector3 pos1 = pair.O1.rb.position; //OPTIMISATION NOTE: These together cause 2x Rigidbody AND 2x Collider Syncs Vector3 pos2 = pair.O2.rb.position; Vector3 dir = new Vector3(pos1.x - pos2.x, pos1.y - pos2.y, pos1.z - pos2.z); //Obtain Distance, return if 0 float distSqr = dir.x * dir.x + dir.y * dir.y + dir.z * dir.z; if (distSqr == 0.0f) { return(Vector3.zero); } //Calculate Magnitude of force float forceMagnitude = G * (pair.O1.rb.mass * pair.O2.rb.mass) / distSqr; // Compare to current largest force for both objects ForceExerter current_max; // 1 if (!strongest_force.TryGetValue(pair.O1.ID, out current_max) || forceMagnitude > current_max.magnitude) { strongest_force[pair.O1.ID] = new ForceExerter(pair.O2.ID, forceMagnitude); } // 2 if (!strongest_force.TryGetValue(pair.O2.ID, out current_max) || forceMagnitude > current_max.magnitude) { strongest_force[pair.O2.ID] = new ForceExerter(pair.O1.ID, forceMagnitude); } //Calculate force float dirMag = Mathf.Sqrt(distSqr); Vector3 force = new Vector3(dir.x / dirMag, dir.y / dirMag, dir.z / dirMag) * forceMagnitude; return(force); }
// Adds the given physics object to the physics engine // Registers and stores all possible pairs ahead of simulation // This is called whenever a new physics object becomes enabled and active. public void AddObject(PhysicsObject physicsObject) { // If pairs list does not exist, create it if (ObjectPairs == null) { ObjectPairs = new List <PhysicsObjectPair>(); } foreach (KeyValuePair <int, PhysicsObject> obj in PhysicsObject.physicsObjects) { //For every other object if (obj.Value != physicsObject) { // Creat new pair PhysicsObjectPair pair = new PhysicsObjectPair(); pair.O1 = physicsObject; pair.O2 = obj.Value; //Check if list already contains pair bool alreadyInList = false; foreach (PhysicsObjectPair objectPair in ObjectPairs.ToList()) { //If pair already exists if ((objectPair.O1 == pair.O1 && objectPair.O2 == pair.O2) || (objectPair.O2 == pair.O1 && objectPair.O1 == pair.O2)) { alreadyInList = true; } } //If pair not in list, add pair if (!alreadyInList) { ObjectPairs.Add(pair); } } } }
Vector3[] PredictOrbit(PhysicsObject _strongestObject, uint steps) { try { Vector3[] positions = new Vector3[steps]; PhysicsObjectPair pair = new PhysicsObjectPair(); pair.O1 = this; pair.O2 = _strongestObject; // Calculate Orbital Period for this //float period = (2.0f * Mathf.PI) * Mathf.Sqrt( Mathf.Pow(Vector3.Distance(pair.O1.transform.position, pair.O2.transform.position),3.0f) / G * ( pair.O1.rb.mass + pair.O2.rb.mass) ); Vector3 position1 = this.transform.position; Vector3 position2 = _strongestObject.transform.position; Vector3 velocity1 = this.rb.velocity - _strongestObject.rb.velocity; //Vector3 velocity2 = _strongestObject.rb.velocity; //Vector3 velocity2 = -velocity1; Vector3 velocity2 = Vector3.zero; //Vector3 velocity2 = _strongestObject.rb.velocity - this.rb.velocity; float mass1 = this.rb.mass; float mass2 = _strongestObject.rb.mass; // Note, this is flawed as it assumes circular orbit float period = (Mathf.PI * 2.0f) * Vector3.Distance(pair.O1.transform.position, pair.O2.transform.position) / velocity1.magnitude; float timestep = period / steps; for (int i = 0; i < steps; i++) { positions[i] = position1; // Calculate force Vector3 force = new Vector3(); //Obtain Direction Vector Vector3 dir = position1 - position2; //Obtain Distance, return if 0 float dist = dir.magnitude; if (dist == 0) { force = Vector3.zero; } //Calculate Magnitude of force float magnitude = PhysicsEngine.G * (mass1 * mass2) / Mathf.Pow(dist, 2); force = dir.normalized * magnitude; // Calculate accelerations Vector3 a1 = -force / mass1; Vector3 a2 = force / mass2; // Update positions position1 += velocity1 * timestep + 0.5f * a1 * timestep * timestep; position2 += velocity2 * timestep + 0.5f * a2 * timestep * timestep; // Update velocities velocity1 += a1 * timestep; velocity2 += a2 * timestep; } return(positions); } catch { lineRenderer.positionCount = 0; return(default);