-18
\$\begingroup\$

I am trying to "squeeze" a game object when it's pressed between two other objects (e.g., "squeezer 1" and "squeezer 2," below) that continue to move towards eachother.

I wish to reduce width of the object so that total area of the game object is maintained while still being between the two squeezers.

enter image description here

How can I achieve this effect?

\$\endgroup\$
3
  • \$\begingroup\$ I am extremely busy right now. But I can leave a hint for you. Area of square is W x H. where H = 1/W. So new formula is W x 1/W. Get the distance of both squeezers by Vector3.Distance and assign it to X-Scale of the victim object ;). And at the same time assign 1/distance to the Y scale. Hope it helps \$\endgroup\$ Dec 16 '15 at 21:09
  • \$\begingroup\$ And btw this formula I got from your given link, you can deal yourself with these kind of problems \$\endgroup\$ Dec 17 '15 at 3:09
  • \$\begingroup\$ Normally I'd close this question as a duplicate but I think in this case it's not worth the trouble as this version has more information and is generally a better description of the problem. \$\endgroup\$
    – user1430
    Dec 18 '15 at 21:26
27
+50
\$\begingroup\$

This effect is very easy to produce in Unity using a couple of Box Colliders, and some basic math. The effect will ressemble the following:

example

This is a very simple model for this problem. First you need 3 gameobjects added to your scene. Each object will contain a BoxCollider2D and a RigidBody2D with gravity removed.

The blue boxes just have a simple update method to move them in a static direction, for the purpose of the demo.

The orange box, checks if a collision is currently occurring. If it is colliding, Unity automatically stops the objects from overlapping each other, as they already have a BoxCollider2D attached.

The only thing you need to do, is determine if the box is being pushed on both sides. If it is only being pushed on one side, then do nothing. If it is being pushed on both ends at the same time, then you adjust the size of the box, while retaining its total area.

So to start, calculate the total area of your orange box:

public float Area;
bool PushedLeft, PushedRight;
float ForceLeft, ForceRight;

void Start () {
    Area = transform.localScale.x * transform.localScale.y;
} 

Then, determine if it is being pushed on both ends at the same time:

void OnCollisionStay2D(Collision2D coll) {

    //Check all points of contacts occuring on this object
    for (int i = 0; i < coll.contacts.Length; i++) {

        //Is the collision occuring to the left of box?
        if (this.transform.position.x > coll.contacts[i].point.x)
        {
            //Is it pushing in? or pulling out?
            Vector2 diff = coll.contacts[i].point - coll.contacts[i].normal;
            if (diff.x < 0)
            {
                PushedLeft = true;
                ForceLeft = 0.1f;
            }
        }
        //collision occuring to the right of box
        else if (this.transform.position.x < coll.contacts[i].point.x)
        {
            //Is it pushing in? or pulling out?
            Vector2 diff = coll.contacts[i].point - coll.contacts[i].normal;
            if (diff.x < 0)
            {
                PushedRight = true;
                ForceRight = 0.1f;
            }
        }
    }
}

Then, if it is being pushed on both ends, Squeeze it so that it alters its shape:

void Update () {

    //Adjust box if being squeezed
    if (PushedLeft && PushedRight) {
        float squeezeForce = ForceLeft + ForceRight;
        float x = transform.localScale.x - squeezeForce * Time.deltaTime;
        float y = Area / x;
        transform.localScale = new Vector2 (x, y);
    }
}

Hoping this helps out someone else that would like to figure out this problem.

\$\endgroup\$
2
  • 2
    \$\begingroup\$ I don't think the sections commented "is it pushing in?" are correct. You're taking a difference between the collision position and the collision normal direction, which doesn't have any particular geometric meaning, and doesn't say anything about the force being exerted at that point. \$\endgroup\$
    – DMGregory
    Dec 19 '15 at 15:25
  • \$\begingroup\$ @DMGregory you are right, that should be checking with the center point of the gameobject, and not the normal. \$\endgroup\$
    – jgallant
    Dec 19 '15 at 15:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.