I want to move an Text object, and the part of code is as follows.
GameObject.transform.position = new Vector3(-210, -200, 0);
When I execute and check the posX of GameObject in Unity, its value becomes -1170(in 1920x1080), -1653.566(16:9). But posY can work properly. I've set the reference convolution to 1920x1080, and I think it may it have something to do with the resolution settings. Is there any thing wrong? Thanks.
If you are talking about unity ui text you should do it like this.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class UITestSO : MonoBehaviour
{
public Text textObject;
void Start ()
{
//Position relative to parent transform
textObject.rectTransform.localPosition = new Vector3 (-210, -200, 0);
//Position in world space
textObject.rectTransform.position = new Vector3 (-210, -200, 0);
}
}
All the UI objects(text, image etc.) are parented by canvas object in unity. Canvas behaves differently based on it's screen space setting as follows -
Screen Space - Overlay : If the screen is resized or changes resolution, the Canvas will automatically change size to match this.
Screen Space - Camera : If the screen is resized, changes resolution, or the camera frustum changes, the Canvas will automatically change size to match as well.
Screen Space - World : The Canvas will behave as any other object in the scene. The size of the Canvas can be set manually using its Rect Transform.
The default setting is Screen Space - Overlay Which is the reason you are getting different position values for your text object on different resolutions.
The unity UI elements uses RectTransform. From unity docs
The Rect Transform component is the 2D layout counterpart of the
Transform component. Where Transform represents a single point, Rect
Transform represent a rectangle that a UI element can be placed
inside. If the parent of a Rect Transform is also a Rect Transform,
the child Rect Transform can also specify how it should be positioned
and sized relative to the parent rectangle.
So, to set position of UI elements use RectTransform's anchoredPosition variable, which sets the position of the pivot of this RectTransform relative to the anchor reference point.
textObject.rectTransform.anchoredPosition = new Vector3 (-10, -10, 0);
Reference to rect transform script API.
In Unity, the transform values you see in the inspector are relative to the gameobject's parent. However, when you try to set value for a gameobject's position (by assigning transform.position = ...), you are dealing with position relative to world's center (i.e Vector(0,0,0)). This holds true for whether you are dealing with 3d or 2d.
So, if the parent object is at Vector(0,0,0), world and local positions would be same. There isn't anything wrong with the resolution. You need to set values relative to your parent.
This is how you set values for objects.
anObject.transform.localPosition = new Vector3 (X, Y, Z);
Although there is nothing stopping you from using the same for 2d workflow, RectTransforms are used over simple Transform.
Related
Alright, I cant find any example of this already done and my attempt is yielding odd results - I need to drag to resize a flattened cube (like a plane, but must have thickness so it was a cube) using a handle in the corner. Like a window on your desktop.
So far Ive created my handle plane and gotten it via script attached to my cube plane. The cube plane and the handle are children of an empty to which the scale is being applied so that the cube plane scales from left to right as desired:
That works, however my attempt at using the delta scale handle position to scale the parent empty scales either way too much or in odd directions:
Awake() {
scaleHandle = GameObject.FindGameObjectWithTag("ScaleHandle");
scaleHandleInitialPos = scaleHandle.transform.localPosition;
}
Update()
{
width += -1*(scaleHandleInitialPos.x - scaleHandle.transform.localPosition.x);
height += -1 * (scaleHandleInitialPos.y - scaleHandle.transform.localPosition.y);
transform.parent.localScale = new Vector3(width, height, thickness);
}
what is wrong here?
Hierarchy:
Transform of the child:
With updating initialPos every Update() OR doing width = scaleHandle.transform.localPosition.x / scaleHandleInitialPos.x; where the white square is the scaleHandle
I'm trying to create a game like WordCookie. I want to use a LineRenderer, so I cannot use the Screen Space - Overlay Canvas Renderer mode. When using either Screen Space - Camera or World View, my Touch position doesn't match the position I get from my RectTransforms.
I access my buttons' transform position by logging:
foreach (RectTransform child in buttons.transform)
{
Debug.Log("assigning" + child.transform);
}
For the touch cooridinates, I simply log the touch.position.
To clarify; I want to trigger my LineRenderrer when the distance between the position vectors is smaller than a certain float. However, whenever I tap on my button to test this, the button logs at (1.2, -2.6) and my touch at (212.2, 250.4).
What could be causing this?
touch.position returns a value using pixel coordinates.
In order to convert to world coordinates you need to use: Camera.ScreenToWorldPoint
Should be something like that:
Vector2 touch = Input.GetTouch(0);
float buttonPositionZ = button.transform.position.z;
Vector3 worldPosition = camera.ScreenToWorldPoint(new Vector3(touch.x, touch.y, buttonPositionZ));
I'm creating 2 GameObjects.
One automatically gets a RectTransform without explicitely adding one, the other doesn't.
In this case, a RectTransform isn't added, but it can be accessed:
GameObject nCanvasGO = new GameObject("CanvasContainer");
Canvas nCanvas = nCanvasGO.AddComponent<Canvas>();
nCanvas.renderMode = RenderMode.WorldSpace;
nCanvasGO.AddComponent<CanvasScaler>();
nCanvasGO.AddComponent<GraphicRaycaster>();
RectTransform rtCanvasGO = nCanvasGO.GetComponent<RectTransform>(); //can be accessed, isn't null
This one does not have a RectTransform:
GameObject nAnimInfo = new GameObject("AnimInfo");
RectTransform rtAnimInfo = nAnimInfo.GetComponent<RectTransform>(); // is null
I would therefore like to ask if adding a Canvas component to a GameObject add a RectTransform or what else might be the reason here.
Thank you.
Yes, Adding a canvas to a Gameobject will automatically change the Transform to a RectTransform. This is because the rect transform is the 2D equivalent of Transform, with some additional functionality like anchoring.
From the Unity docs:
The Rect Transform component is the 2D layout counterpart of the Transform component. Where Transform represents a single point, Rect Transform represent a rectangle that a UI
element can be placed inside. If the parent of a Rect Transform is also a Rect Transform, the child Rect Transform can also specify how it should be positioned and sized relative to the parent rectangle.
The docs don't actually clearly state anywhere that a transform gets replaced by RectTransform automatically though...
Furthermore Canvas depends on RectTransform, and can thus not be used without having a RectTransform. You can see ths when you try to delete the rect transform from a canvas. It will pop up saying "Can't remove RectTransform because Canvas depends on it".
Any other UI component you add to a GameObject will also automatically add the Recttransform component (I.E image, text etc.). this has the same reason as Canvas, that they depend on RectTRansform.
You will also notice that any GameObject you make that is a child of a canvas will also have a RectTransform by default, so that it can anchor itself relative to the parents (canvas in this example) rect transform. You can delete the rectTransform from these Objects as long as none of its components depend on RectTransform. Though i don't see why this would be desired, as any child of a canvas should be some form of UI like an image or text. And should thus require the RectTransform.
I have added Cube to scene and I scaled and put to position ( 0, 0, 0 ).
I am scaling that Cube with code attached to Cube
IEnumerator Start() {
StartCoroutine("DoSomething", 2.0F);
yield return new WaitForSeconds(1);
StopCoroutine("DoSomething");
}
IEnumerator DoSomething(float someParameter) {
while (true) {
transform.localScale += new Vector3(0, 0.1f, 0);
yield return null;
}
}
but Cube scales on both sides, to top and bottom. I want to scale with same factor but that bottom of Cube stays on same position.
I tried to set new position between transform.localScale += new Vector3(0, 0.1f, 0); and yield return null; but I don't know how to get exact amount.
( I tried to read
Mesh planeMesh = gameObject.GetComponent<MeshFilter>().mesh;
Bounds bounds = planeMesh.bounds;
bounds.size.y;
before and after scale and add to
transform.position.y difference between
boundsAfter.size.y and boundsBefore.size.y
but it moves too much.
How to solve this ?
You can actually do this in two ways.
METHOD 1:
Change pivot point from an external application.
Create a simple Cube in a 3D software such as Maya then position the pivot point to the bottom of the cube and then export it Unity. This should work out of the box.
METHOD 2:
Parent the Cube to an empty GameObject.
Steps:
A.Create a an Empty GameObject.
B.Move the new GameObject to the position of the Cube then move the y axis of that new GameObject to the bottom of the cube. The y-pos must be positioned precisely by zooming in. See to the animation below for more information.
C.Now drag the Cube to the that new GameObject and the cube should be the child of that new GameObject. You can now attach the script in your question to that new GameObject and it should scale the cube on one side only. Don't forget to remove the old scaling script that is directly attached to the cube.
Image Tutorial. High quality version here.
You can use Slider for the purpose. I was designing a Loading bar for which I needed to Increase width of the loader according to the download that is progressed. You can disable its handle, and use custom Sprite for loading fill percentage. You can also use custom Sprite for background. To use Slider, go to Menu Bar -> GameObject -> UI -> Slider. Or instead You can Add a Slider Component from the Inspector for the GmaeObject you want (Select the GameObject you want to add Slider -> In the Inspector click Add Component -> UI -> Slider. Now Set Fill Rect and other Options). You can set Slider from Left to Right, Right to Left, Bottom to Top, or Top to Bottom.
In the Script
using UnityEngine.UI;
public class SliderExample : MonoBehaviour
{
public Slider slider; // Drag and Drop Slider GameObject in Unity Inspector
float percentageCompleted;
void Update()
{
slider.value = percentageCompleted;
// specify percentage Completed, if required Divide by 100 as Slider values are from 0 to 1 or set Max Value in Inspector as 100
}
}
You can also watch this Brackeys video for some help regarding setting up the Slider "https://www.youtube.com/watch?v=YMj2qPq9CP8".
I currently have an item placement system for building. It works by instantiating a "ghost" of the object that shows where it can be placed, the ghost (semi-transparent) object is attached to the camera and instantiates the object in its place when the player clicks.
I get the position at which to keep the ghost object like so:
var pos = transform.position + transform.forward * placeDistance; // A position 'someDistance' in front of the player
pos.y = Terrain.activeTerrain.SampleHeight(pos); // Get the position at the surface of the terrain to place the object
firePlaceable.transform.position = pos + Vector3.up * 0.001f; // 'halfHeight' is used in case the pivot is not on the base
Now.. I need the object to rotate according to the terrain so that the fire place is placed more or less correctly rotated. Any ideas? What would the best plan be?
Use the terrain normal vector at the place' position.
For example you could do a raycast straight down from the fireplace. The resulting hit contains a normal that is your place' up vector.
By thinking of it... I assume you already doing a raycast to get the position to place the fireplace right?
Use the placement raycast to get the up vector instead of making a new one.
So basicly do
fireplace.transform.up = clickPlaceHit.normal;