- Home /
How to align GameObjects based on their corner not the center point
By default when we set position (x,y) of a GameObject, it does so based on its center point. I would like to place object A over object B based on B's top left corner. What is happening now is if I get position of B and assign it to position of A then A's center point align with B's center point. What I want is A's top left corner align with B's top left corner. Please refer the image.
Answer by Fariborzzn · May 03, 2021 at 06:38 AM
The easiest way is to create an empty object position it on left corner of your A object then make A Game Object child of this game object Now move your Parent(not child) to proper position. Hope this helps and maby try to look at this Set new Origin using empty GameObject Best regards Fariborz
Edit 2 : Hey @Orbica So yeah it makes sense to not creating parent and do all of the hard work at runtime so maybe try this
SpriteRenderer B = GetComponent<SpriteRenderer>();
Vector2 upperLeft = new Vector2 (-B.bounds.extents.x, B.bounds.extents.y);
now we have upper left position of B .if we try to set the position of A to this position we should probably have this
so what we need next is to match the left upper corner of A to B .. Just add half of the size of A to its X and minus the half of the size of the A to its Y . sorry I am not at home to try this and not gonna be for some time I got some break from game dev so maybe it will answer your question feel free to try it and let me know if this worked.if this didn't help come back to see what we can do about it :) . best regards Fariborz
Thanks for reply. But in my case objects are getting generated at runtime. e.g. I have a puzzle grid board where cells are getting generated at runtime. So I cannot create empty game object at design time and place it at corner.
Thanks for your pointers. I have finally figured it out. In my case overlapping object can be rotate so corners may be always Top Left, they can be Top right or Bottom Right, based on what degree we have rotated the object (as Top left corner can become Top right after 90 degree rotation). So we need to manipulate addition or subtraction of x and y based on corners we are using to overlap object.
I have put the code in my next comment as I cannot put it here due to 3000 characters limit.
Answer by rh_galaxy · May 04, 2021 at 01:39 PM
MidpointB-HalfSizeB(gives B top left corner) + MidpointA...
Answer by OblicaStudio · May 06, 2021 at 12:30 PM
Here is complete code.
Call GetOverlapAlignment() function. First parameter will be be your primary object (e.g. which you are dragging or moving), second parameter will be your secondary object on which you want to place your primary object, third parameter will be which corner you want to use to match the placing.
public enum Corner
{
TopLeft,
TopRight,
BottomRight,
BottomLeft
}
// Returns coordinates of specified corner of a game object
public static Vector2 GetCorner(GameObject gameObject, Corner corner)
{
Vector2 extents = gameObject.GetComponent<Renderer>().bounds.extents;
Vector2 cornerPosition = gameObject.transform.position;
if (corner == Corner.TopLeft)
{
cornerPosition.x -= extents.x;
cornerPosition.y += extents.y;
}
else if (corner == Corner.TopRight)
{
cornerPosition.x += extents.x;
cornerPosition.y += extents.y;
}
else if (corner == Corner.BottomRight)
{
cornerPosition.x += extents.x;
cornerPosition.y -= extents.y;
}
else if (corner == Corner.BottomLeft)
{
cornerPosition.x -= extents.x;
cornerPosition.y -= extents.y;
}
return cornerPosition;
}
// Get the position of game object with respect to game object it is overlapping beneath.
// Game objects will be aligned based on their corners and not the center points (as it is default in Unity)
public static Vector2 GetOverlapAlignment(GameObject primaryGameObject, GameObject secondaryGameObject, Corner cornersToMatch)
{
Vector2 position = new Vector2();
Vector2 primaryBoundsExtent = primaryGameObject.GetComponent<Renderer>().bounds.extents;
Vector2 secondaryGameObjectPosition = GetCorner(secondaryGameObject, cornersToMatch);
if (cornersToMatch == Corner.TopLeft)
{
position = new Vector2(secondaryGameObjectPosition.x + primaryBoundsExtent.x, secondaryGameObjectPosition.y - primaryBoundsExtent.y);
}
else if (cornersToMatch == Corner.TopRight)
{
position = new Vector2(secondaryGameObjectPosition.x - primaryBoundsExtent.x, secondaryGameObjectPosition.y - primaryBoundsExtent.y);
}
else if (cornersToMatch == Corner.BottomRight)
{
position = new Vector2(secondaryGameObjectPosition.x - primaryBoundsExtent.x, secondaryGameObjectPosition.y + primaryBoundsExtent.y);
}
else if (cornersToMatch == Corner.BottomLeft)
{
position = new Vector2(secondaryGameObjectPosition.x + primaryBoundsExtent.x, secondaryGameObjectPosition.y + primaryBoundsExtent.y);
}
return position;
}