Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
1
Question by fel3web · Nov 06, 2020 at 08:49 PM · physicsrigidbodyforces

Solar System Simulator Orbits Not Working

Hi. I am working on a simple solar system simulator and am trying to get 1 sphere to orbit another. this works fine for a few seconds at about simspeed = 400 before having a physics freakout (jittering) and teleporting before orbiting at a further distance. any help or even ideas as to what could be going wrong are much appreciated. I have an empty scene with a gamemanager object and 2 spheres, as well as a camera and light of course. my gamemanager has the scripts gamemanager and commonfuncs on it, while the spheres have a mesh renderer and filter plus a rigidbody and collider and finally the gravitybody script. the orbiting gravitybody has a start velocity of (-0.632,0.632,0.632) and a mass of 1 while the one being orbited has no start velocity and a mass of 20. sorry for the code dump but i cannot narrow this down.

CommonFuncs (Vector Math in here):

 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 
 public class CommonFuncs : MonoBehaviour
 {
     public float pythagHypot3(Vector3 vector) //Get the hypotenuse using 3d pythagoras
     {
         float a = vector.x; float b = vector.y; float c = vector.z;
         float hsq = a*a + b*b + c*c;
         return(Mathf.Sqrt(hsq));
     }
     public Vector3 unitVector(Vector3 vector) //Get the unit vector of any vector3
     {
         float magnitude = pythagHypot3(vector);
         return(vector / magnitude);
     }
     public Vector3 vectorSq(Vector3 vector)
     {
         float x = Mathf.Pow(vector.x,2);
         float y = Mathf.Pow(vector.y,2);
         float z = Mathf.Pow(vector.z,2);
         return(new Vector3(x,y,z));
     }
     public Vector3 divByVector(float numerator, Vector3 divisor)
     {
         float x = numerator / divisor.x;
         float y = numerator / divisor.y;
         float z = numerator / divisor.z;
         return(new Vector3(x,y,z));
     }
     public Vector3 vectorMult(Vector3 a, Vector3 b)
     {
         float x = a.x * b.x;
         float y = a.y * b.y;
         float z = a.z * b.z;
         return(new Vector3(x,y,z));
     }
     public Vector3 absVector(Vector3 vector)
     {
         float x = Mathf.Abs(vector.x);
         float y = Mathf.Abs(vector.y);
         float z = Mathf.Abs(vector.z);
         return(new Vector3(x,y,z));
     }
 }

And finally gravitybody:

 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 
 public class GravityBody : MonoBehaviour
 {
     Gamemanager gamemanager;
     Rigidbody rigidbody;
     public List<GravityBody> attractedTo = new List<GravityBody>();
     public Vector3 velocity;
     Vector3 lastForce;
     public bool hasOwnGravity;
     public float mass;
     void Awake()
     {
         //Get Components
 
         gamemanager = GameObject.Find("GameManager").GetComponent<Gamemanager>();
         rigidbody = GetComponent<Rigidbody>();
 
         //Init part 1
 
         if(hasOwnGravity){ //Add to ownGravityBodies if applicable
             gamemanager.ownGravityBodies.Add(this);}
 
         rigidbody.velocity = velocity; //Apply Starting Velocity
         rigidbody.mass = mass; //Apply Mass
 
         lastForce = Vector3.zero; //Set First Last Force
     }
     void Start()
     {
         //Init part 2
         foreach(GravityBody ownGravityBody in gamemanager.ownGravityBodies)
         {
             if(ownGravityBody != this)
             {
                 attractedTo.Add(ownGravityBody);
             }
         }
     }
     void FixedUpdate()
     {
         UpdateForce();
     }
     void UpdateForce()
     {
         //Calculate Force
         Vector3 currentForce = new Vector3(0f,0f,0f);
         foreach(GravityBody body in attractedTo)
         {
             currentForce += GetForceOneBody(body);
         }
         currentForce *= gamemanager.simSpeed;
 
         //Apply Force
         rigidbody.AddForce(-lastForce);
         rigidbody.AddForce(currentForce);
         lastForce = currentForce;
     }
     Vector3 GetDistance(GravityBody _otherPoint)
     {
         Transform otherPoint = _otherPoint.gameObject.transform;
         Transform thisPoint = this.gameObject.transform;
 
         float x = otherPoint.position.x - thisPoint.position.x;
         float y = otherPoint.position.y - thisPoint.position.y;
         float z = otherPoint.position.z - thisPoint.position.z;
 
         return(new Vector3(x,y,z));
     }
     Vector3 GetForceOneBody(GravityBody otherBody)
     {
         CommonFuncs funcs = gamemanager.funcs;
         Vector3 distance = GetDistance(otherBody);
         Vector3 unitVector = funcs.unitVector(distance);
         distance = funcs.absVector(distance); //Obtain distance, after raw value is used for unit vector
         Vector3 fractionPart = funcs.divByVector(otherBody.mass * mass,funcs.vectorSq(distance)); //The section of the equation that is a fraction
         Vector3 forceVector = gamemanager.gravityConstant * funcs.vectorMult(fractionPart,unitVector);
         return(forceVector);
     }
     void OnCollisionEnter()
     {
         rigidbody.isKinematic = true;
     }
 }
 


Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

2 Replies

· Add your reply
  • Sort: 
avatar image
0
Best Answer

Answer by andrew-lukasik · Nov 08, 2020 at 04:50 PM

- Rigidbody class is NOT designed nor fit for solar system simulations.

Hardcoded value limits (like 1e9 kg for mass) alone will render those calculation impractical. Rigidbody component is not for all the physics but just for very game-specific simple mechanical physics i.e.: approximating dynamics between similar (+-human) sized objects.

- Code above is full of little math mistakes and unnecessary calculations; those probably compound.


However, here's fixed version of your code. It works but it's a dead end for many reasons.

simulation

 using System.Collections.Generic;
 using UnityEngine;
 
 [RequireComponent( typeof(Rigidbody) )]
 [RequireComponent( typeof(SphereCollider) )]
 public class GravityBody : MonoBehaviour
 {
     [SerializeField] float _initialSpeed = 0.1f;
     [SerializeField][Range(1,1e9f)] float _initialmass = 1e9f;
     static List<GravityBody> _instances = new List<GravityBody>(10);
     Rigidbody _rigidbody;
     Vector3 _resultantForce;
     void Awake ()
     {
         _instances.Add( this );
 
         _rigidbody = GetComponent<Rigidbody>();
         _rigidbody.useGravity = false;
         _rigidbody.isKinematic = false;
         _rigidbody.drag = 0;
         _rigidbody.angularDrag = 0;
         _rigidbody.mass = _initialmass;
 
         _rigidbody.velocity = transform.forward * _initialSpeed;
     }
     void FixedUpdate ()
     {
         _resultantForce = default(Vector3);
         float m1 = _rigidbody.mass;
         Vector3 p1 = transform.position;
         foreach( GravityBody otherBody in _instances )
         {
             Vector3 p2 = otherBody.transform.position;
             Vector3 forceDir = p2 - p1;
             float distSq = forceDir.sqrMagnitude;
             if( distSq>0f )
             {
                 float m2 = otherBody._rigidbody.mass;
                 _resultantForce += forceDir.normalized * ( 6.6743e-11f * ( (m1*m2) / distSq ) );
             }
         }
         
         _rigidbody.AddForce( _resultantForce , ForceMode.Force );
     }
 }

No Rigidbody version

better simulation

Requires com.unity.mathematics package.

 using System.Collections.Generic;
 using UnityEngine;
 using Unity.Mathematics;
 public class GravityBody : MonoBehaviour
 {
     [Header("Body:")]
     [SerializeField][Tooltip("[m/s]")] float _initialSpeed = 0.1f;
     [SerializeField][Tooltip("[kg]")] float _mass = 5.972E24f;
     [SerializeField][Tooltip("[kg/m^3]")] float _density = 5000f;
     
     [Header("Read Only:")]
     [SerializeField][Tooltip("[N]")] double3 _resultantForce;
     [SerializeField][Tooltip("[kg*m/s]")] double3 _momentum;
     [SerializeField][Tooltip("[m/s]")] double3 _velocity;
     [SerializeField][Tooltip("[m]")] float _radius = 0;
     [SerializeField][Tooltip("[{m,m,m}]")] double3 _position;
 
     static List<GravityBody> _instances = new List<GravityBody>(10);
 
     #if UNITY_EDITOR
     void OnValidate ()
     {
         _velocity = (double3)(float3)( transform.forward * _initialSpeed );
         _momentum = _mass * _velocity;
         _radius = SphereRadius( volume: _mass/_density );
         _position = (double3)(float3) transform.position;
     }
     #endif
 
     void OnEnable () => _instances.Add( this );
     void OnDisable () => _instances.Remove( this );
     void FixedUpdate ()
     {
         // calculate resultant force;
         float m1 =  this._mass;
         _resultantForce = default(double3);
         for( int i=_instances.Count-1 ; i!=-1 ; i-- )
         {
             GravityBody other = _instances[i];
 
             double3 forceDir = other._position - _position;
             double distSq = math.lengthsq( forceDir );
             if( distSq>0d )
             {
                 float m2 = other._mass;
                 if( distSq > math.pow(math.max(_radius,other._radius),2f) )
                     _resultantForce += math.normalize(forceDir) * Force( m1:m1 , m2:m2, distSq:distSq );
                 else
                 {
                     // collision!
                     _radius = SphereRadius( SphereVolume(_radius) + SphereVolume(other._radius) );
                     _mass += m2;
                     _momentum += other._momentum;
                     _position = math.lerp( _position , other._position , math.saturate(m2/(m1+m2)) );
                     transform.position = (Vector3)(float3) _position;
 
                     Debug.Log( $"<b>{name}</b> destroys <b>{other.name}</b> in collision, distSq:{distSq}" , gameObject );
                     _instances.RemoveAt(i);
                     Destroy( other.gameObject );
                 }
             }
         }
 
         // calculate new velocity:
         double dt = Time.fixedDeltaTime;
         _momentum += _resultantForce * dt;
         _velocity = _momentum / _mass;
 
         // update object position:
         _position += _velocity * dt;
         transform.position = (Vector3)(float3) _position;
     }
 
     static double Force ( double m1 , double m2 , double distSq ) => 6.6743e-11f * ( (m1*m2) / distSq );
     static float SphereVolume ( float radius ) => 4f/3f * math.PI * math.pow(radius,3f);
     static float SphereRadius ( float volume ) => math.pow( ( 3f * volume )/( 4f*math.PI ) , 1f/3f );
     
     #if UNITY_EDITOR
     void OnDrawGizmos () => Gizmos.DrawSphere( transform.position , _radius );
     [ContextMenu("Randomize parameters")]
     void RandomizeParameters ()
     {
         _initialSpeed *= UnityEngine.Random.Range( 0.6f , 1.4f );
         _mass *= UnityEngine.Random.Range( 0.6f , 1.4f );
         _density *= UnityEngine.Random.Range( 0.6f , 1.4f );
         OnValidate();
     }
     [ContextMenu("Randomize initial speed")] void RandomizeInitialSpeed () { _initialSpeed *= UnityEngine.Random.Range( 0.6f , 1.4f ); OnValidate(); }
     [ContextMenu("Randomize mass")] void RandomizeMass () { _mass *= UnityEngine.Random.Range( 0.6f , 1.4f ); OnValidate(); }
     [ContextMenu("Randomize density")] void RandomizeDensity () { _density *= UnityEngine.Random.Range( 0.6f , 1.4f ); OnValidate(); }
     [ContextMenu("Validate parameters")] void ValidateParameters () => OnValidate();
     #endif
 }

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
1

Answer by Spemble · Nov 06, 2020 at 11:18 PM

Does rigidbody.AddForce() only apply the force for the current physics step? In the example in the docs on Rigidbody.AddForce(), it shows the force being added each FixedUpdate but not subtracting the force from last frame.

Try taking out the rigidbody.AddForce(-lastForce); in gravitybody on line 57.

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image fel3web · Nov 08, 2020 at 09:35 AM 0
Share

Thanks for your answer. It certainly fixed that bug but now everything is rather odd so i suspect this might not be the answer. thanks though!

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

263 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Physics update rate problems 1 Answer

Net Force apply in Unity? 1 Answer

Move rigidbody to position and still have forces act on it 0 Answers

How can I simulate a short-distance attraction between RigidBodies A and B, with the mutual pull always being between the center of A and the closest point in B's collision mesh? 0 Answers

Any way to have a rigidbody not be affected by forces, but still collide with other objects? 2 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges