Search Unity

Resolved Parenting vs fixed joint for modular spaceships

Discussion in 'Physics for ECS' started by ScallyGames, May 22, 2023.

  1. ScallyGames

    ScallyGames

    Joined:
    Sep 10, 2012
    Posts:
    47
    In my current project we are trying to allow building modular spaceships consisting of different blocks (see image).



    The current implementation is done using parenting where all blocks belonging to a ship are parented under a ship entity containing a dynamic rigidbody.
    This comes with a couple of issues though:
    - No good way to obtain entity from raycast / collision event (they are grouped into a compound collider, the colliding entity is that of the ship rigidbody and there are only dirty hacks to try to find the entity from the compound collider index https://forum.unity.com/threads/get...s-on-compoundcolliders-best-practices.923258/)
    - The ship should be able to be dynamically reordered / extended during runtime. This would require to repeatedly rebuild the compound collider.


    As an alternative I have now tried to rewrite everything to use fixed joints instead.
    The current implementation is to still have a ship entity which has a dynamic physics body but have every single block as their own dynamic physics body attached to the ship with fixed joints (with a set offset defined by the position on the imaginary grid of the ship).
    This somewhat works with ~15 blocks, however just adding an additional block causes the entire system to jitter / oscillate. The stability of the physics solver was the reason I tried to avoid joints in the first place.
    Instead of connecting all blocks to a ship entity I could try to interconnect all adjacent blocks instead but my intuition is that this would cause even worse instabilities.


    In the long term I would like to add networking and synchronize ships over different clients which might influence the decision on which method to favor.



    I'd love to hear any idea or recommendation on what would be the best way to tackle this problem or what to avoid.
    Right now it seems like fixed joints are what should be the best solution but seems impracticable due to instability in the resulting physics simulation.
     
  2. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,510
    Try increasing the physics rate and/or the physics solver iterations:
    • Project Settings > Time: Set "Fixed Timestep" to 0.01 instead to 0.02. This will make the physics to run at 100 Hz instead of the default 50 Hz.
    • Project Settings > Physics (for 3D physics): Increase "Default Solver Iterations" and "Default Solver Velocity Iterations". For example, I have a physics-intense project with 100 iterations in both.
    • Project Settings > Physics 2D (for 2D physics): Increase "Velocity Iterations" and "Position Iterations".
    I recommend you to configure one parameter at each time and check the result. Try extreme values in each case. You should then get a good picture on which are the values that work best.
     
  3. daniel-holz

    daniel-holz

    Unity Technologies

    Joined:
    Sep 17, 2021
    Posts:
    278
    These settings only work with built-in physics, not DOTS physics.

    To increase the number of solver iterations use the "Physics Step" authoring component.
    For the timestep, have a look at the FixedRateCatchUpManager.
     
  4. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,510
    Oh! Sorry for that. As I'm watching both forums it's not the first time I reply to a DOTS physics question assuming it's about regular physics.
     
    daniel-holz likes this.
  5. daniel-holz

    daniel-holz

    Unity Technologies

    Joined:
    Sep 17, 2021
    Posts:
    278
    No worries! Always happy to see you contributing, no matter in what forum. :)
     
    Edy likes this.
  6. n3b

    n3b

    Joined:
    Nov 16, 2014
    Posts:
    56
    @ScallyGames actually you don't need joints for that. ColliderBlobInstance contains Entity field where you can pass your modules to. I have something similar with compound colliders
     
    daniel-holz likes this.
  7. ScallyGames

    ScallyGames

    Joined:
    Sep 10, 2012
    Posts:
    47
    @n3b that sounds really interesting.
    Do you have any links on the usage of ColliderBlobInstance?
    I tried to look it up but there seems to be very little information on that API.

    Pretty much the only things I could find was the link to the autogenerated API struct and one usage in the query physics samples.
     
  8. daniel-holz

    daniel-holz

    Unity Technologies

    Joined:
    Sep 17, 2021
    Posts:
    278
    Maybe @n3b can confirm, but I believe they are suggesting you could create compound colliders each time you make a modification to your modular spaceship using the
    CompoundCollider.Create(NativeArray<ColliderBlobInstance> children)
    function and in the individual
    ColliderBlobInstance
    elements set the
    Entity
    property to the Entity you want to associate that spaceship module to.

    This property is copied over to the Entity field of the
    CompoundCollider.Child
    elements that are produced by this Create function and can be retrieved in collider query results through use of the collider key, for example
    RaycastHit.ColliderKey
    .
    With the collider key you can access the child in the compound collider using
    CompoundCollider.GetChild
    .

    You can this way associate your child colliders in the compound collider with your conceptual high level spaceship modules (represented by the Entities) even though all colliders are in a single compound.

    As it says here in the
    ColliderBlobInstance
    , the Entity field is meant as a "user data" field for exactly that purpose.

    upload_2023-6-5_15-7-50.png

    Hope this helps.
     
    ScallyGames and U_ru_Ru like this.
  9. n3b

    n3b

    Joined:
    Nov 16, 2014
    Posts:
    56
    Yeah, precisely that

    Code (CSharp):
    1. public static Entity GetHitEntity(this RaycastHit hit, in NativeArray<RigidBody> bodies)
    2. {
    3.     var collider = bodies[hit.RigidBodyIndex].Collider;
    4.     if (collider.Value.Type != ColliderType.Compound) return hit.Entity;
    5.          
    6.     var key = hit.ColliderKey;
    7.     collider.Value.GetChild(ref key, out var childCollider);
    8.     return childCollider.Entity;
    9. }
     
    ScallyGames, U_ru_Ru and daniel-holz like this.