Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice

Question SoftBody Jelly issue 2D

Discussion in 'Scripting' started by Naisha_01, Dec 30, 2023.

Thread Status:
Not open for further replies.
  1. Naisha_01


    Nov 16, 2019
    Hey everyone! im making a jelly merge game in which the jellies drop from the top and if the jelly merge with the same one, the new jelly appears.

    The Issue occurs whenever the jelly collide with the edge of the platform, it stuck
    This is a jelly star which is connected with sprint joint.
    upload_2023-12-31_0-58-45.png upload_2023-12-31_1-7-2.png

    upload_2023-12-31_1-13-55.png upload_2023-12-31_1-15-29.png

    Does anyone know why this happens and how one can fix it? i have played with the setting of spring joint2D but this case occurs continuesly...

    Thank u in advance for any input :)

    Attached Files:

  2. Kurt-Dekker


    Mar 16, 2013
    Your jelly is being impaled and the spike looks like it is going between your colliders.

    You might fix it by adding more colliders or by making the colliders larger.

    But I imagine at some point it will always be possible to impale a soft body.

    Maybe put an invisible larger "blob" on the end of the spikes, kind of how they protect construction workers from reinforcing bars with the little orange end caps??

    Screen Shot 2023-12-30 at 12.35.08 PM.png
    Nad_B, CodeRonnie and Naisha_01 like this.
  3. Naisha_01


    Nov 16, 2019
    adding more colliders and making the collider larger will also have no impact, the issue will remain there : (
    similarly i added the circle collider at the edge of the spike just to replicate the 3D "Blob", but the jelly is dropping in a speed it still stuck in the edges : (
  4. samana1407


    Aug 23, 2015
    Setting up physics is often not easy. Try first changing some parameters on the RigidBody2D component (for example, collision detection methods). Or project-wide physics settings, by increasing the number of iterations in Velocity/Position Iteration (Edit - Project Settings - Physics2D).

    Or try a different approach to creating soft bodies. For example, manually configuring many objects and joints is not always convenient and takes a lot of time. So, let's simplify our task a bit.

    Let me be able to set up the desired shape on the scene using PolygonCollider2D, and then somehow turn this shape into a soft body. Let's create some kind of segment between each pair of points, consisting of a circle and a rectangle. Something like a joint. Each such segment is a separate object with a rigid body and, consequently, two colliders.
    But as expected, these segments simply fall apart:

    Some advantage of the segment idea is that there are practically no gaps between them, and theoretically, such an object has fewer chances of being pierced.

    To prevent the segments from falling apart, let's connect them using FixedJoint2D. Of course, connect each segment (where the circle is) to the next segment (the beginning of the rectangle). And for elasticity, let's increase the Frequency property:

    Of course, it's necessary to add the ability to change the thickness of the segments. After all, the thinner the segment, the more chances it has to pass through a thin object, and that's not what you want. Therefore, the thicker the segment, the more reliable collision processing becomes.

    And Frequency affects how strongly the shape of the object will strive to maintain its initial state.

    In the end, I ended up with something like this:

    Of course, this is just an idea and a rough sketch. During testing, there were cases where objects pierced through as well. But as you can see in the gif, the thin needle pierces the floor, and in the game, there is no need to replicate the same behavior. If an object pierces through, you can try increasing the radius of the segments as well.

    Unfortunately, I currently don't have the time to provide you with a well-adjusted version. I can only share what I have at the moment.

    How to try it out:

    • Create an object with PolygonCollider2D.
    • Give the collider the desired shape.
    • Disable the collider or make it a trigger (so that it doesn't interfere in the future).
    • Add a script to the object and pass a reference to your collider.
    You can create a soft body right in the editor by calling CreateSegments from the context menu. The context menu is invoked by right-clicking on the script header in the inspector, for example. After creating the soft body, you can edit its properties. And when the game is running, you can also create soft bodies using the Space key.

    Important: Since these objects consist only of colliders, they are not visible in the scene. Therefore, in the physics settings, I marked the option to always show colliders (ProjSettings - Physics2D - Gizmos - AllColliders).

    I apologize for the lengthy text. And since such a soft body is only at the idea stage, there is still a lot of work ahead, such as linking such a body with the bones of the sprite for deformation, etc.

    Code (CSharp):
    1. using System.Linq;
    2. using UnityEngine;
    4. public class SoftObject2 : MonoBehaviour
    5. {
    6.     public PolygonCollider2D PolyCollider;
    8.     [Min(0.01f)]
    9.     public float Radius = 0.3f;
    11.     [Min(0)]
    12.     public float Frequency = 3f;
    14.     [Min(0.01f)]
    15.     public float GravityScale = 1f;
    17.     private Rigidbody2D[] _rBodies;
    18.     private FixedJoint2D[] _joints;
    19.     private BoxCollider2D[] _boxes;
    20.     private CircleCollider2D[] _circles;
    22.     [ContextMenu(nameof(CreateSegments))]
    23.     private void CreateSegments()
    24.     {
    25.         Vector3[] pointsGlobal = PolyCollider.points.Select(p => PolyCollider.transform.TransformPoint(p)).ToArray();
    27.         int amount = PolyCollider.points.Length;
    29.         _rBodies = new Rigidbody2D[amount];
    30.         _joints = new FixedJoint2D[amount];
    31.         _boxes = new BoxCollider2D[amount];
    32.         _circles = new CircleCollider2D[amount];
    34.         Transform holder = new GameObject("SoftBodyParent").transform;
    36.         for (int i = 0; i < pointsGlobal.Length; i++)
    37.         {
    38.             Vector3 currentPoint = pointsGlobal[i];
    39.             Vector3 nextPoint = pointsGlobal[(i + 1) % pointsGlobal.Length];
    41.             float distance = Vector3.Magnitude(nextPoint - currentPoint);
    43.             GameObject go = new GameObject("Segment_" + i);
    44.             go.transform.position = Vector3.Lerp(currentPoint, nextPoint, 0.5f);
    45.             go.transform.right = nextPoint - currentPoint;
    47.             go.transform.SetParent(holder);
    49.             BoxCollider2D box = go.AddComponent<BoxCollider2D>();
    50.             box.size = new Vector2(distance, Radius * 2f);
    51.             _boxes[i] = box;
    53.             CircleCollider2D circle = go.AddComponent<CircleCollider2D>();
    54.             circle.radius = Radius;
    55.             circle.offset = new Vector2(-distance / 2, 0);
    56.             _circles[i] = circle;
    58.             _rBodies[i] = go.AddComponent<Rigidbody2D>();
    59.             _rBodies[i].gravityScale = GravityScale;
    61.             _joints[i] = go.AddComponent<FixedJoint2D>();
    62.             _joints[i].frequency = Frequency;
    63.         }
    65.         for (int i = 0; i < _joints.Length; i++)
    66.         {
    67.             int iNext = (i + 1) % _joints.Length;
    69.             var nextJoint = _joints[iNext];
    70.             nextJoint.connectedBody = _rBodies[i];
    71.             nextJoint.anchor = nextJoint.transform.InverseTransformPoint(pointsGlobal[iNext]);
    72.         }
    73.     }
    75.     private void OnValidate()
    76.     {
    77.         if (_rBodies == null)
    78.             return;
    80.         for (int i = 0; i < _rBodies.Length; i++)
    81.         {
    82.             _rBodies[i].gravityScale = GravityScale;
    83.             _boxes[i].size = new Vector2(_boxes[i].size.x, Radius * 2);
    84.             _circles[i].radius = Radius;
    85.             _joints[i].frequency = Frequency;
    86.         }
    87.     }
    89.     private void Update()
    90.     {
    91.         if (Input.GetKeyDown(KeyCode.Space))
    92.             CreateSegments();
    93.     }
    94. }
    Naisha_01, spiney199 and MelvMay like this.
  5. unity_42A886663119F7C9BBE9


    Oct 18, 2023
  6. samana1407


    Aug 23, 2015
    Back when this topic emerged, I tried to implement a convenient binding of a rigid body to a sprite grid (based on skin). But I couldn't find any universal way. The object's shape itself and the desired behavior of softness have a significant impact. And I realized that for each type of object (thin, long, round, square, etc.), you have to come up with your own unique "tricks" both in physics settings and in the sprite and skeleton grid to make this shape behave the way you want. So I abandoned this idea, realizing that a universal approach simply doesn't exist.
  7. eclipse130300


    Dec 6, 2019
    Hm, how do you think guys it is possible to solve penetration problem in 3d physics?
    Segments should consist from...capsules and triangular prisms???
  8. Kurt-Dekker


    Mar 16, 2013
    Sure, let us know what you find out. But when you do, please don't necro-post another thread.

    Make your own post to discuss your findings. Posts are FREE and necro-posting is explicitly prohibited by forum rules.
    eclipse130300 likes this.
Thread Status:
Not open for further replies.