Search Unity

Unity box2d + Farseer (box2d) to simulate a path

Discussion in '2D' started by robhuhn, Dec 10, 2013.

  1. robhuhn

    robhuhn

    Joined:
    Jun 21, 2009
    Posts:
    113
    Hi,

    since Unity uses box2d for the 2D environment I was wondering if it's possible to simulate the bodies path with a second box2d engine. If it would be possible to get the bodies in both engines in sync, then one could use the additional engine as a simulation engine and execute steps manually but also have the built-in engine in use.

    I downloaded Farseer from the Asset Store, set up a second physics world, copied all unity bodies into farseer and adjusted some configs.

    Code (csharp):
    1.     body = BodyFactory.CreateRectangle(world,
    2.                                        gObj.transform.localScale.x, //width
    3.                                        gObj.transform.localScale.y, //height
    4.                                        1f, //density
    5.                                        new FVector2(gObj.transform.position.x, gObj.transform.position.y)); // position
    6.  
    7.     //apply unity physics properties to Farseer bodies
    8.     body.Rotation = gObj.transform.rotation.eulerAngles.z * Mathf.Deg2Rad;
    9.     body.Friction = gObj.collider2D.sharedMaterial.friction;
    10.     body.Restitution = gObj.collider2D.sharedMaterial.bounciness;
    11.  
    12.     if(gObj.rigidbody2D != null)
    13.     {
    14.         body.Mass = gObj.rigidbody2D.mass;
    15.         body.AngularDamping = gObj.rigidbody2D.angularDrag;
    16.         body.LinearDamping = gObj.rigidbody2D.drag;
    17.     }

    The result by now is that the unity bodies and farseer bodies are in sync for about 10 seconds but losing sync then. Before they lose sync, they're jumping around and contacting the walls multiple times all in sync.


    $Screen Shot 2013-12-10 at 09.38.35.png
    $Screen Shot 2013-12-10 at 09.38.41.png
    $Screen Shot 2013-12-10 at 10.18.04.png

    The images are showing the unity bodies (white opaque) behind the half transparent farseer bodies (green and red). The last screenshot shows the time when the bodies lose sync.
    Velocity and position iterations are 8, 3 in both engines. Fixed timestep is set to 0.0001 (the higher it is, the earlier it get out of sync).

    There are a bunch of Farseer settings I didn't touch - I hope they are all the same in Unity since most can't be changed in Unity:

    Code (csharp):
    1.     public const float MaxFloat = 3.402823466e+38f;
    2.     public const float Epsilon = 1.192092896e-07f;
    3.     public const float Pi = 3.14159265359f;
    4.  
    5.     public static bool FixedUpdate = true;
    6.  
    7.     public static bool EnableDiagnostics = true;
    8.  
    9.     public static int VelocityIterations = 8;
    10.  
    11.     public static int PositionIterations = 3;
    12.  
    13.     public static bool ContinuousPhysics = true;
    14.    
    15.     public static int TOIVelocityIterations = 8;
    16.  
    17.     public static int TOIPositionIterations = 20;
    18.  
    19.     public const int MaxSubSteps = 8;
    20.  
    21.     public static bool EnableWarmstarting = true;
    22.  
    23.     public static bool AllowSleep = true;
    24.  
    25.     public static int MaxPolygonVertices = 8;
    26.  
    27.     public static bool UseFPECollisionCategories = true;
    28.  
    29.     public static Category DefaultFixtureCollisionCategories = Category.Cat1;
    30.  
    31.     public static Category DefaultFixtureCollidesWith = Category.All;
    32.  
    33.     public static Category DefaultFixtureIgnoreCCDWith = Category.None;
    34.  
    35.     public static bool ConserveMemory = false;
    36.  
    37.     public const int MaxManifoldPoints = 2;
    38.  
    39.     public const float AABBExtension = 0.1f;
    40.  
    41.     public const float AABBMultiplier = 2f;
    42.  
    43.     public const float LinearSlop = 0.005f;
    44.  
    45.     public const float AngularSlop = 0.03490659f;
    46.  
    47.     public const float PolygonRadius = 0.01f;
    48.  
    49.     public const int MaxTOIContacts = 32;
    50.  
    51.     public const float VelocityThreshold = 1f;
    52.  
    53.     public const float MaxLinearCorrection = 0.2f;
    54.  
    55.     public const float MaxAngularCorrection = 0.1396264f;
    56.  
    57.     public const float Baumgarte = 0.2f;
    58.     public const float TOIBaumgarte = 0.75f;
    59.  
    60.     public const float TimeToSleep = 0.5f;
    61.  
    62.     public const float LinearSleepTolerance = 0.01f;
    63.  
    64.     public const float AngularSleepTolerance = 0.03490659f;
    65.  
    66.     public const float MaxTranslation = 2f;
    67.  
    68.     public const float MaxTranslationSquared = 4f;
    69.  
    70.     public const float MaxRotation = 1.570796f;
    71.  
    72.     public const float MaxRotationSquared = 2.467401f;
     
  2. robhuhn

    robhuhn

    Joined:
    Jun 21, 2009
    Posts:
    113
  3. ehudros

    ehudros

    Joined:
    Nov 14, 2013
    Posts:
    5
  4. robhuhn

    robhuhn

    Joined:
    Jun 21, 2009
    Posts:
    113
    Yes using two farseer worlds would work but I thought using the built-in box2d engine for the main physics and a secondary for simulation would be better for performance and doesn't affect the usual workflow.

    I had another try without an additional engine by setting the timescale to a high value, tracking the rigidbody2D and then resetting it to it's defaults but that was even worse.

    Hopefully Unity will implement the opportunity to add a second world and control it's steps or another way to predict the path of (complex) bodies. Until then it seems to be best to refuse the built-in engine in this case.
     
    Last edited: Dec 12, 2013
  5. ehudros

    ehudros

    Joined:
    Nov 14, 2013
    Posts:
    5
    How complicated is it to update game objects to reflects their Farseer object state? Also, is Farseer's performance adequate on mobile devices?
     
  6. robhuhn

    robhuhn

    Joined:
    Jun 21, 2009
    Posts:
    113
    It's a while back since I used farseer in a bigger project - As far as I remember you only have to attach the BodyComponent to your sprite. The performance is also good on mobile if you don't have that much bodies.
     
  7. Robin_B

    Robin_B

    Joined:
    Aug 5, 2013
    Posts:
    2
    Very interesting. Could you upload a sample project with the comparison in it, robhuhn? I'd like to play around with it as well!

    Edit: actually I managed to set it up now, and I'm seeing the same issues as you - after the first collision the two simulations desynchronize minimally, which of course amplifies over time.

    Edit2: I get more accurate results when I change baumgar to 0.6f in the Farseer Settings. It still desynchronizes after a while, but much later.
     
    Last edited: Dec 18, 2013
  8. robhuhn

    robhuhn

    Joined:
    Jun 21, 2009
    Posts:
    113
    hi robin, unfortunately I didn't manage to get it working properly and changing the configs would be just a guessing game for me. Actually I think there are double-precision issues with the c++ box2d lib and the ported c# box2d version - not sure about that. So I'm not working on it anymore. I hope unity will add a feature like this in the future.

    Did you have some further success?

    Happy new year!
     
  9. ehudros

    ehudros

    Joined:
    Nov 14, 2013
    Posts:
    5
    I was actually able to get a working accurate prediction by using Farseer as both my main physics engine and a secondary (simulation) engine.
    Obviously this is at the cost of not using the built in box2d engine, which I'm sure is faster than farseer, but for a simple scene it's good enough.
     
  10. jpthek9

    jpthek9

    Joined:
    Nov 28, 2013
    Posts:
    944
    How would I go about converting the physics system to use the XZ plane instead of the XY plane? That's something I really need for my top-down 3D shooter project that only needs 2d physics.