3
\$\begingroup\$

I am Instantiating a lot of Rectangles of different sizes (ranging from 3 to 18 units) and they all have attached this script, which should cycle through all the GameObject List which contains them.

enter image description here

It should automatically avoid any overlap, but unfortunately sometimes it gets stuck with some rectangles that remain moving and all the others stop. When this occurs, my program can't continue and blocks in an infinite loop.

enter image description here

Here's the script:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class Cell : MonoBehaviour {

    private float squareDistance;

    float xShift = 0;
    float yShift = 0;

    //float globalStrength = 0;

    public bool hasStopped = false;

    private Vector2 oldPos = new Vector2();
    //private Vector2 oldPos2 = new Vector2();

    public Vector3 direction;

    // Use this for initialization
    void Start () {

    }

    // Update is called once per frame
    void Update () {

        if(Placer.work) {
            float strength;

            List<GameObject> cells = Placer.cells;

            for (int i=0; i < cells.Count; i++) {
                if(cells[i] != this.gameObject) {
                    if(isOverlapping(cells[i])) {

                        direction = transform.position - cells[i].transform.position;

                        strength = 1; //+ globalStrength;

                        /*if(globalStrength > 0) {
                            globalStrength = 0;
                        }*/

                        direction.Normalize();

                        xShift += strength * direction.x;
                        yShift += strength * direction.y;

                    }
                }
            }

            transform.position = new Vector3(Mathf.Round(transform.position.x + xShift), Mathf.Round(transform.position.y + yShift), transform.position.z);

            xShift = 0;
            yShift = 0;

            if (transform.position.x == oldPos.x && transform.position.y == oldPos.y) {
                hasStopped = true;
            } else {
                hasStopped = false;
            }
            //oldPos2 = oldPos;

            /*if(oldPos2.x == transform.position.x && oldPos2.y == transform.position.y) {
                globalStrength = 2;
                Debug.Log ("si2");
            }*/

            oldPos = new Vector2 (transform.position.x, transform.position.y);

            /*if(oldPos2.x == oldPos.x && oldPos2.y == oldPos.y) {
                globalStrength = 3;
                Debug.Log ("Si");
            }*/
        }
    }

    private bool isOverlapping(GameObject obj) {
        Vector2 size = new Vector2 (GetComponent<Renderer> ().bounds.size.x, GetComponent<Renderer> ().bounds.size.y);

        if (pointInside (obj, new Vector2 (transform.position.x + 1 - size.x / 2, transform.position.y + 1 - size.y / 2))) {
            return true;
        }

        if (pointInside (obj, new Vector2 (transform.position.x - 1 + size.x / 2, transform.position.y + 1 - size.y / 2))) {
            return true;
        }

        if (pointInside (obj, new Vector2 (transform.position.x + 1 - size.x / 2, transform.position.y - 1 + size.y / 2))) {
            return true;
        }

        if (pointInside (obj, new Vector2 (transform.position.x - 1 + size.x / 2, transform.position.y - 1 + size.y / 2))) {
            return true;
        }

        return false;

    }

    /**
     * With this method we verify if a Vector2 is inside a GameObject.
    */
    private bool pointInside(GameObject obj, Vector2 point) {

        Vector2 objSize = new Vector2 (obj.GetComponent<Renderer> ().bounds.size.x, obj.GetComponent<Renderer> ().bounds.size.y);
        if ((point.x >= (obj.transform.position.x - objSize.x / 2)) &&
            (point.x <= (obj.transform.position.x + objSize.x / 2)) &&
            (point.y >= (obj.transform.position.y - objSize.y / 2)) &&
            (point.y <= (obj.transform.position.y + objSize.y / 2))) {

            return true;
        }

        return false;
    }

    public bool getHasStopped() {
        return hasStopped;
    }

}

I have tried with some workarounds, which you can see commented in the code; none of them fixes completely the problem.

What can I do to fix it?

\$\endgroup\$
  • \$\begingroup\$ It is unclear to me what you want to achieve. Are you trying to generate them not overlapping? Are you trying to move them a bit until none overlap after you generate them? Will they be moving a bit each frame and they should not overlap at that moment? Have you been able to achieve what you want with fewer rectangles and it stopped working at some point? \$\endgroup\$ – Alexandre Vaillancourt Mar 26 '15 at 12:09
  • \$\begingroup\$ @AlexandreVaillancourt They are already generated, but they overlap. The script is attached to every rectangle. Each frame they'll move by 1 unit in direction opposite to where they are. When they're still, they have hasStopped which tells to the main script if they have stopped moving. The problem happens with lots of rectangles (150) and with fewer (30). \$\endgroup\$ – Stefa168 Mar 26 '15 at 12:54
3
\$\begingroup\$

You seem to have rectangles that are sandwiched:

  1. You have rectangles A, B and C
  2. A directly above and is overlapping B, which is above and overlapping C.
  3. The update for A is done, pushes it a bit up.
  4. The update for B is done, pushes it a bit up because of C, and a bit down because of A.
  5. B hasStopped because it did not move because your [x|y]Shift is cumulative for all of the neighbours.
  6. Deadlock because this is the situation of a chain in your rectangles.

You might want to try and make sure you 'de-overlap' them one by one right when you create them.

Or you could try and push them only further away from the centre, never closer to it.

\$\endgroup\$
  • 1
    \$\begingroup\$ I implemented your answer and I also added a further control, which increases the strength variable the more time it takes to displace all the rectangles. \$\endgroup\$ – Stefa168 Mar 26 '15 at 14:23

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.