- Home /
Help with orbits
I'm rather new to Unity and C#, and I'm trying to create a script that can set a 2d object into a circular orbit around another 2d object before any frame updates, regardless of positions or mass. I have a second functional script that automatically applies a gravitational force on all objects using G. Here's what I have so far:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class OrbitInitializer : MonoBehaviour
{
// Hold G in this script
private static float G;
// Body to orbit
public Rigidbody2D toOrbit;
// This objects rigidbody
public Rigidbody2D rb;
// Used to determine direction of orbit
public bool IsClockwise = false;
// Start is called before the first frame update
void Start()
{
// Fetch the Rigidbody2D of the object to orbit
toOrbit = GetComponent<Rigidbody2D>();
Vector2 toOrbitPos = toOrbit.transform.position; // Find position of body to orbit
Vector2 toOrbitDir = toOrbit.transform.position - rb.transform.position; // Find direction body to orbit is in
float dist = toOrbitDir.magnitude; // Find distance from body to orbit (center) to this
float mass = toOrbit.mass; // Find the mass of the body to orbit
// 90 degree rotation
Quaternion rotation = Quaternion.Euler(0, 0, 90);
// Swap direction of orbit from counter-clockwise to clockwise
if (IsClockwise == true)
{
rotation = Quaternion.Euler(0, 0, -90);
}
// Direction to apply force for orbit
Vector2 orbitDir = rotation*toOrbitDir;
orbitDir = orbitDir.normalized;
// Define this scripts G as the G in Attractor.cs
G = Attractor.G;
// Magnitude of orbital force
double velocity = Math.Sqrt((G * mass) / dist);
// Final calculation for orbit vector
Vector2 orbit = orbitDir * (float)velocity;
// Add force
//rb.AddForce(orbit);
rb.velocity = orbit;
}
}
Whenever I run a game with this script attached to one of two "planets", I receive an error message:
Rigidbody2D.velocity assign attempt for 'planet' is not valid. Input velocity is { NaN, NaN }.
Odds are my problem is something simple I've overlooked, but any help is appreciated.
Answer by darksider2000 · May 09, 2020 at 05:20 PM
Your issue doesn't lie in the code you posted. I ran your code in a test project and it worked just fine.
The problem is either in the Attractor code or in the interaction between the two. If you post the Attractor code we'll have a fighting chance ;)
EDIT: Problem was with the OrbitInitializer code after all.
Your problem was with this line:
// Fetch the Rigidbody2D of the object to orbit
toOrbit = GetComponent<Rigidbody2D>();
Instead of fetching the target's rigidbody, you were fetching your own rigidbody. As a result you were telling the rigidbody to orbit around itself. (Distance was 0 and you were dividing by distance, thus resulting in NaNs)
I'll add here the error that's posted is most likely from rb.velocity = orbit, and it's telling you that you're trying to assign a value to that velocity of Vector2(not a number, not a number). I agree with @darksider2000 it's very likely your G isn't set with what you expect from Attractor so you're not getting proper numbers in the 'orbit' variable. Could do a quick Debug.Log("G: " + G); to check after G is assigned.
Hm, the gravity script was working well enough when it came to simple pulling objects towards each other. Admittedly it's not my own script so it wasn't made specifically for orbits. using System.Collections; using System.Collections.Generic; using UnityEngine;
public class Attractor : $$anonymous$$onoBehaviour
{
// Gravitational Constant
public const float G = 0.006674f;
// List of attractors
public static List<Attractor> Attractors;
// Attach own rigidbody to
public Rigidbody2D rb;
void FixedUpdate ()
{
foreach (Attractor attractor in Attractors)
{
// For each attractor in the list, if it itsn't this object, call Attract()
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)
{
Rigidbody2D rbToAttract = objToAttract.rb;
Vector2 direction = rb.position - rbToAttract.position;
float distance = direction.magnitude;
if (distance == 0f)
return;
float force$$anonymous$$agnitude = G * (rb.mass * rbToAttract.mass) / $$anonymous$$athf.Pow(distance, 2);
Vector2 force = direction.normalized * force$$anonymous$$agnitude;
rbToAttract.AddForce(force);
}
}
@wilmcal8 I found your problem, check my edit above
Daang, I should've seen that. Thanks so much for helping me out!
Your answer
Follow this Question
Related Questions
How do you create a continuous physics simulation in Unity? 1 Answer
Can I access Physics2dSettings in Project Settings via script 1 Answer
How to get animated sprite to adhere to gravity? 2 Answers
Handling Large number of Active Rigidbody Evaluations 2 Answers
Check if 2D Player is grounded with Physics2D.Linecast 1 Answer