1
\$\begingroup\$

In my game, I have Tiled "rooms" that were imported with Tiled2Unity. All of these rooms have walls that are defined by Polygon Collider 2D objects. In the event of a cave or dungeon, I'd like to implement torches. Currently, I literally randomly place torches in each room, which is pretty good for lighting, but looks ridiculous.

After the room is added, rather than randomly place torches anywhere, I'd like to have them placed along the inside of the collider. Is there a good way to make this happen?

Edit:

One of my first attempts was to get a list of all of the points in all colliders in a given room after it's instantiation. I was starting with something like this.

GameObject _roomGO = 
   (GameObject)Instantiate(_room.gameObject, new Vector3 (-6.5f, 6.5f, 0f), Quaternion.identity);

List<PolygonCollider2D> _polyList =
   _roomGO.GetComponentsInChildren<PolygonCollider2D>().ToList();

However, this only gets the points from the first collider, whereas I need the points for all colliders in the room GameObject. Additionally, I'm not sure how those points are stored in such a way that I could create a List or Array of lines, then evaluate those lines to determine which are inside the room (as opposed to along the outside, so nothing in the set [(x,0),(x,-13),(0,y),(13,y)].

Once I had a list of lines that weren't part of that set, I could choose a point on the line and drop in a torch.

Edit2 - images:

enter image description here enter image description here

Edit 3:

Thank to @SP., I've used some of his code as shown here:

        if (_torches)
    {
        Transform _roomGOLayer = _roomGO.transform;
        int numTorch = rndObjects.Next(2,4);

        List<PolygonCollider2D> _polyList = _roomGO.GetComponentsInChildren<PolygonCollider2D>().ToList();

        foreach (PolygonCollider2D polCol in _polyList)   
        {
            foreach (Vector2 point in polCol.GetPath(0))
            {
                Debug.Log(point.x +" : "+ point.y);//you will be using these values

                GameObject _to = Instantiate(_torch, new Vector2(point.x, point.y), Quaternion.identity) as GameObject;
                _to.transform.parent = _roomGOLayer;
                _to.transform.position = _to.transform.parent.transform.position + new Vector3 (point.x, point.y, 0f);
            }
        }
    }

The biggest problem I'm having up front is that _polyList is only getting the first collider definition. I think if I could solve that, I'd be in good shape.

enter image description here

\$\endgroup\$
  • \$\begingroup\$ Can you include an image of a typical case, showing the shapes of the colliders? (And where you'd ideally like the torches placed) There's a few ways this could be set up, so seeing what you've got so far will help clarify what next steps are needed. \$\endgroup\$ – DMGregory Aug 11 '16 at 1:27
3
\$\begingroup\$

You can get the elements of the paths. Then spawn torch there. Store them as Vector2. Very simple implementation below.

public GameObject mSphere;
PolygonCollider2D polCol;

void Start ()
{
    polCol = GetComponent<PolygonCollider2D>();

    foreach (Vector2 point in polCol.GetPath(0))//Implemented on outer path only, you will need multiple paths
    {
        Debug.Log(point.x +" : "+ point.y);//you will be using these values

        Instantiate(mSphere, new Vector2(point.x, point.y), Quaternion.identity);
    }
}

Result:

enter image description here

If you get the list of colliders, so you have the points of them as well.

Use {(x1+x2)/2, (y1+y2)/2} for determining the midpoint between (x1, y1) and (x2, y2) as well as next points.

\$\endgroup\$
  • \$\begingroup\$ Awesome answer and example - thank you. I'll try this tomorrow and probably will promote your answer unless someone else has something to offer. \$\endgroup\$ – Jesse Williams Aug 11 '16 at 3:07
  • \$\begingroup\$ This is a good start, but I'm having trouble capturing all of the colliders in a single room. _polyList is only coming back with the first set. \$\endgroup\$ – Jesse Williams Aug 11 '16 at 18:19
  • \$\begingroup\$ GetPath(0) is just one (circular) path. You have to iterate for all the paths(GetPath(1/2/3 and so on) ) of one polygon collider. I think your _polyList is fine. Check with Debug.Log(). \$\endgroup\$ – Sourav Paul Aug 11 '16 at 18:38
  • \$\begingroup\$ _polyList appears to only be getting Element 0 from my list of nine paths when I debug. Eventually, I'll need to randomize it a bit as I don't want every point to receive a torch object, but for now I'd be happy to have one dropped on every point in all colliders to start with lol. \$\endgroup\$ – Jesse Williams Aug 11 '16 at 18:40
  • 1
    \$\begingroup\$ In your case, there may be two easy solutions. Optimize your colliders to one main circular path. That way you apply over points or aligned with it. Another way is to make sure one point is not being used more than twice to calculate mid points. That will rule out inter geometry midpoints. If your case is precision intense this will help for sure. \$\endgroup\$ – Sourav Paul Aug 15 '16 at 2:48

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.