Search Unity

Planetary gravity approximation

Discussion in 'Scripting' started by mstevenson, Feb 10, 2010.

  1. mstevenson

    mstevenson

    Joined:
    Sep 24, 2009
    Posts:
    189
    I've been playing around with a stripped down planetary gravity sim, and I'm trying to optimize the code a bit. I'm having trouble wrapping my brain around this - are these two snippets essentially equivalent?

    (Note: one rigidbody is being affected by multiple sources of gravity, and its own gravitational pull is not taken into account)

    Attempt #1:
    Code (csharp):
    1. var difference : Vector3 = body.transform.position - planetPosition;
    2. var gravityForce = mass / Mathf.Pow(Vector3.Distance(body.transform.position, planetPosition), 2);
    3. body.AddForce(-difference.normalized * gravityForce, ForceMode.VelocityChange);
    Attempt #2:
    Code (csharp):
    1. var difference : Vector3 = body.transform.position - planetPosition;
    2. body.AddForce(-difference.normalized * mass / difference.sqrMagnitude, ForceMode.VelocityChange);
    #2 seems much cleaner and possibly even faster to execute. Is this the way to go?
     
  2. andeeeee

    andeeeee

    Joined:
    Jul 19, 2005
    Posts:
    8,768
    Unless you're already taxing the CPU it might not be noticeable, but the second example would be faster. Vector3.Distance uses Pythagoras, and so involves a square root. This is rather a slow operation. Mathf.Pow is also not very fast - just using x * x is much faster when calculating squares. However, the sqrMagnitude property means that you don't need to do that here anyway.
     
  3. mstevenson

    mstevenson

    Joined:
    Sep 24, 2009
    Posts:
    189
    Interesting... thanks!

    I'm curious, why is Mathf.Pow(x,2) slower than x*x? Does the same hold true for larger exponents?
     
  4. Tinus

    Tinus

    Joined:
    Apr 6, 2009
    Posts:
    437
    My guess would be that Pow has a lot of code that is there to handle cases like Pow(x, 1.43986732) and other less regular cases. Pow will probably use that code even for simple cases like Pow(x, 2), giving you a noticeable amount of overhead.
     
  5. uhahaha

    uhahaha

    Joined:
    Jan 5, 2010
    Posts:
    42
  6. rom

    rom

    Joined:
    Jul 2, 2006
    Posts:
    265
  7. mstevenson

    mstevenson

    Joined:
    Sep 24, 2009
    Posts:
    189
    My game is very cartoony, with tiny moons zipping around their planets. I agree that physics might not be the way to go - once the initial conditions are set up, I'm just letting the simulation run.

    I'd actually strongly considered using Kepler's laws, and spent a whole day trying to work it out. Unfortunately I have such poor knowledge of higher level math I wasn't able to muddle through it. I'm still willing to try if there's some sample code I can start from.

    Here's my current solution:
    A gravity component applies a constant gravitational force to the moon. An orbit component applies a computed initial velocity that will yield a desired orbit. Four orbital parameters are provided by the level designer:
    1. The positions of the moon and planet (just their transform.position)
    2. The periapsis - The distance from center of planet to the nearest point in the moon's orbit. The moon is assumed to start at the apoapsis.
    3. The orbital speed - effectively the star's gravity
    4. Optional: A starting angle. 0 is at the apoapsis, 180 is the periapsis, 90 is directly on the ellipse's minor axis.
    So basically, the level designers needs only to place the planet and moon in the editor, then define a periapsis in the inspector. Or, ignore the periapsis and the script will provide a circular orbit by default. Unity's physics work reasonably well for maintaining the orbit, but it tends to drift slightly over time.
     
  8. mstevenson

    mstevenson

    Joined:
    Sep 24, 2009
    Posts:
    189
  9. ZoomDomain

    ZoomDomain

    Joined:
    Aug 30, 2012
    Posts:
    150
    because maths Pow is a function that relies on Pow(float,float), so you can do Pow(1.432 , 8.432) and any similar calculations, you can even have negative nums in the second part. when you write that you call a float operation direct on the CPU, and intel has a list of what the different maths ops take in cycles on their tech specs, see a page 764 on here http://www.intel.com/content/www/us...-ia-32-architectures-optimization-manual.html