Unity2D - uniform positioning of transforms with different sizes - unity3d

I have a rectangle (sprite) and I need to place different game objects (sprites) inside that rectangle but so they are all "aligned" by their bottoms.
For the life of me, I cannot make it work in Unity.
Say that my box has a height of 5.
I want to place the different size objects so they are all "resting" at the 2.5 y axis inside the box.
Does anyone know how I can do that since transform.position measures from the center of the GameObject?
Thanks!

Don't use transform.position, use RectTransform properites, as they take anchor points into account. In particular you need to set the anchor position for the sprite in the prebab / inspector and then use RectTransform.anchoredPosition to position it.

Related

How to align tilemap, grid and sprites to center? (Unity 2D Tilemap)

I am making a game similar to Rimworld and I have issues aligning the tilemap, grid and sprites so that they all work as intended functionally and visually.
The default offset for the tile anchor is 0.5, 0.5, 0 and this works entirely until I drop a sprite in the center of the tile, where it appears to be positioned bottom-left (with the sprite's pivot set to Center).
This is a problem because I'd have to manually set an offset (0.5, 0.5, 0) for every single object I instantiate to match the visuals of the tilemap. I tried setting the tile anchor to 0 but then the tilemap moves while the grid position stays the same which messes up click detection. (if only I could move the grid back by (-0.5, -0.5, 0)?
Is there an elegant and easy solution for all of this?
To get a perfect custom alignment for a tilemap or sprite the easiest solution is to take a empty gameobject as spawner , take the position of that empty spawner object and and then instantiate those tile or other prefab at the exact location where you kept those spawner objects by your choice.
something a friend of mine told me, is that instead of trying to align it to the grid so it always moves in the center, just hold ctrl while using the move tool on the sprite that you are moving. It can get annoying, but it works :)
basicly if you change the sprite pivot for top-left or something different of center should work, for me works perfectly.
I have the same problem with my 2d game. when I want to put the tiles, they place with some offset.
You can change the pivot value in the sprite editor for any sprite ( tiles, character, ...) to a custom pivot like (0,0,0), I suggest center value for the pivot.
You can change Tile Ancher for any Tilemap objects too.
this helps you to put anything to map how you are comfortable.

(Unity + 2D) Change UI Button position issue

The last few days I've been stuck with a headache of a problem in Unity.
Okay, I won't go into details with my game, but I've made a super-simple example which represents my issue.
I have a 2D scene these components:
When the scene loads, and I tap the button this script executes:
Vector3 pos = transform.position;
pos.x -= 10;
transform.position = pos;
I have also tried this code:
transform.position = Camera.main.WorldToScreenPoint(new Vector3(0, 0, 0));
The problem is, that when I click the button, the x-pos of the object sets to -1536 which is not as expected. Picture shows the scene after the button has been clicked. Notice the Rect Transform values:
So I did a little Googling and found out about ScreenToWorldPoint, WorldToScreenPoint etc but no of these conversions solves my problem.
I'm pretty sure I'm missing someting here, which probably is right in front of my, but I simply can't figure out what.
I hope someone can point me in the right direction.
Best regards.
The issue is that you are using transform.position instead of rectTransform.anchoredPosition.
While it's true that UI elements are still GameObjects and do have the normal Transform component accessible in script, what you see in the editor is a representation of the RectTransform that is built on top. This is a special inspector window for UI elements, which use the anchored positioning system so you can specify how the edges line up with their parent elements.
When you set a GameObject's transform.position, you are providing a world space position specified in 3D scene units (meters by default). This is different from a local position relative to the canvas or parent UI element, specified in reference pixels (the reference pixel size is determined by the canvas "Reference Resolution" field).
A potential issue with your use of Camera.WorldToScreenPoint is that that function returns a position specified in pixels. Whereas, as mentioned before, setting the transform.position is specified in scene units (i.e. meters by default) and not relative to the parent UI element. The inspector, though, knows it's a UI element so instead of showing you that value, it is showing you the world position translated to the UI's local coordinates.
In other words, when you set the position to zero, you are getting the indices of whatever pixels happen to be over the scene's zero point in your main camera's view, and converting those pixel numbers to meters, and moving the element there. The editor is showing you a position in reference pixels (which are not necessarily screen pixels, check your canvas setting) relative to the object's parent UI element. To verify, try tilting your camera a bit and note that the value displayed will be different.
So again you would need to use rectTransform.anchoredPosition, and you would further need to ensure that the canvas resolution is the same as your screen resolution (or do the math to account for the difference). The way the object is anchored will also matter for what the rectTransform values refer to.
Try using transform.localposition = new Vector3(0,0,0); as your button is a child of multiple game objects. You could also try using transform.TransformPoint, which should just convert localpos to worldpos.
The issue is that your button is inside of another object. You want to be changing the local position. transform.localPosition -= new Vector3(10, 0, 0)
As #Joseph has clearly explained, you have to make changes on your RectTransform for your UI components, instead of change Transform.
To achieve what you want, do it like this:
RectTransform rectTransform = this.GetComponent<RectTransform>();
Vector2 anchoredPos = rectTransform.anchoredPosition;
anchoredPos.x -= 10;
rectTransform.anchoredPosition = anchoredPos;
Just keep in mind that this 10 are not your 3D world space units (like meters or centimeters).
Try these things because I did not understand what you were trying to do
Try using transform.deltaposition
Go to the canvas and go then scale with screen size then! You can use transform.position = new Vector3(transform.position.x -10,transform.position.y, transform.positon.z)
And if this doesn't work
transform.Translate(new Vector3(transform.deltaposition.x - 10,transform.deltaposition.y, transform.deltaposition.z);
I have a better idea. Instead of changing the positions of the buttons, why not change the values that the buttons represent?
Moving Buttons
Remember that the buttons are GameObjects, and every gameobject has a position vector in its transform. So if your button is named ButtonA, then in your code you want to get a reference to that.
GameObject buttonA = GameObject.Find("ButtonA");
//or you can assign the game object from the inspector
Once you have a reference to the button, you can proceed in moving it. So let's imagine that we want to move ButtonA 10 units left.
Vector3 pos = buttonA.transform.position;
pos.X -= 10f;
buttonA.transform.position = pos;

SpriteKit sprite position inside node tree

Currently working on a simple 2D game, where I have player character that is split into multiple sprites (head, torso, legs, arms,...).
I have absolute coordinates right in Aseprite (if I take individual sprite and position them I get correct coordinates).
When I put everything into swift and use negative y instead of positive everything gets totally weird.
For example in Aseprite I have coordinates as follow: head (30, 17), torso (30, 24) and legs (28, 35). Everything aligns perfectly.
In SpriteKit I extend SKNode class and put every subsprites inside with just negative number for y. So instead of going up, I draw down. It looks like that coordinates give in pixels are not correct - sprites are off by few pixels. Mostly is off y coordinate but in some cases (character rotation) also x.
How to get from those absolute upper-left coordinates to correct SpriteKit coordinates then?
Ok I figured what was wrong (several things):
your parent class can be SKNode, but children has to have set anchor point at (0,1)
when changing texture of child sprite, always make sure that sprite size is set to new size of texture. If not it will use previous texture size and resize new texture to old size. This introduces additional problems with positioning. So you have to call: child.size = child.texture!.size() (I used force unwrap because I set (new) texture one step before so I'm 100% sure it exists.
when setting new texture set anchor point again (it seems it gets reset when changing texture of child sprite).

Unity3D localposition relation to parent

I'm trying to position some gameObjects relative to it's parent. I'm using localposition, but the gameObjects are not placed well. If I use local position the parent's width is considered to be 1, right? So if I have a plane unity3d considers it to be a 1X1 square.
I tried to put some models in the local position (1, 1) but they are not placed in the top right corner of the plane...
Do you guys have some thoughts of what might be the problem?
You're incorrect: the parents' width is the x/y/z scale of the parent; local co-ordinates are still measured in world units. If your plane is 100x100 horizontally, and centred at 0,0,0 then you need to put the model to (50,0,50) to be at the corner.

stick a sprite to another when it collide with it

so I have a sprite that is created every second and that is moving at a random position (sprite1) and another sprite that has a fixed position (sprite2). I would like that when sprite1 collide with sprite2, sprite1 is like sticked to it (it stops moving and is sticked to it) . How can I do this please ? sorry for my english I'm french :/
p.s : sprite2 is rotating with accelerometer, so if sprite1 collide with it I would like that it rotate too :)
I think, you can try to use box2d to do this. It will help to detect collisions and to manage rotations, movement, etc.
I think, you can do it simply in Cocos2d.
1) First set the rect for sprite1 and sprite2 using CGRectMake(x,y,width,height)
2) As you told sprite1 is moving at random position and sprite2 is fixed to particular position, you can check them collide by using CGRectIntersectsRect([sprite1 bounds],[sprite2 bounds]).
3) if it intersects, set sprite1.position = sprite2.position
Note: you said sprite1 is rotating, rect can be fit only to the regular bodies. if you want exact collision or physical properties for sprite better you can go for box2d.
If you don't want to use Box2d (which can handle circle collisions), you can try something like this:
1.) Detect collision, is the distance between the two circles center point (x,y), less than the sum of the two circles radius.
2.) Make the Sprite1 stick to Sprite2, Stop the movement of Sprite1, and save the relative delta (x,y) to Sprite2, then whenever Sprite2 moves or rotates apply the same delta movement and rotation to Sprite1.