In Unity, is there a way to detect in the camera's field of view, if a cube object is infront of a text component which is in World Space? Such that the cube blocks the text in camera's FoV?
//this is your object that you want to have the UI element hovering over
GameObject WorldObject;
//this is the ui element
RectTransform UI_Element
//first you need the RectTransform component of your canvas
RectTransform CanvasRect=Canvas.GetComponent<RectTransform>();
//then you calculate the position of the UI element
//0,0 for the canvas is at the center of the screen, whereas WorldToViewPortPoint
//treats the lower left corner as 0,0. Because of this, you need
//to subtract the height / width of the canvas * 0.5 to get the correct position.
Vector2 viewportPosition=Cam.WorldToViewportPoint(WorldObject.transform.position);
Vector2 WorldObject_ScreenPosition=new Vector2(
((ViewportPosition.x*CanvasRect.sizeDelta.x)-(CanvasRect.sizeDelta.x*0.5f)),
((ViewportPosition.y*CanvasRect.sizeDelta.y)-(CanvasRect.sizeDelta.y*0.5f)));
//now you can set the position of the ui element
UI_Element.anchoredPosition=WorldObject_ScreenPosition;
It helped me in the past and i hope it will help you too
font: https://answers.unity.com/questions/799616/unity-46-beta-19-how-to-convert-from-world-space-t.html
Related
I am making a game in Unity and I have a Canvas set to Screen Space - Overlay and it has that background green as you can see from the image. I also have a RawImage with the background blue as a child of the Canvas and the player will have to draw an object like a car or a house inside the RawImage.Right now, the line Instantiates in a random position on the screen even if I give it the coordinated (0, 0).
What I need help with is to find a way to convert the coordinates so I only work with the inside coordinates of the RawImage. For example, the (0, 0) coordinate I will pass to the line, has to be converted to the bottom-left corner of the RawImage. and the maximum width or height should also depend on the RawImage width and height.
Here is the CreateLine function I have for now:
public void CreateLine(int x, int y)
{
currentLine = Instantiate(linePrefab, Vector3.zero, Quaternion.identity);
currentLine.transform.parent = GameObject.Find("GameMenu(Clone)").transform; //Make the line a child of the Canvas named GameMenu
lineRenderer = currentLine.GetComponent<LineRenderer>();
lineRenderer.SetPosition(0, new Vector3(x, y, 99));
lineRenderer.SetPosition(1, new Vector3(x, y, 99));
}
Any amount of help will be greatly appreciated. Have a great day!
I have rawimage inside a game object and want to move it by drag and drop but must not exceed parent gameobject
I can move the raw image but It can go anywhere in the canvas
for that I calculate the border points and allow it if it stays in border but mouses eventdata.position gives world position.
how can I transform mouse position to position in game object?
You can translate the mouse position to world position then world position to local position
Vector3 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
Vector3 objectRelative = object.transfrom.InverseTransformPoint(mousePos);
Another approach is to use collider bounds, these aren't always super accurate however, depending on the shape of your object
In your child object's update method, make sure you have [ExecuteInEditMode] at the top of your script
if(!Application.isPlaying){
Vector3 minBounds, maxBounds;
Collider parentCollider = transform.parent.gameObject.GetComponent<Collider>();
minBounds = parentCollider.bounds.min;
maxBounds = parentCollider.bounds.max;
float xPos = Mathf.Clamp(transform.position.x, minBounds.x, maxBounds.x);
float yPos = Mathf.Clamp(transform.position.y, minBounds.y, maxBounds.y);
float zPos = Mathf.Clamp(transform.position.z, minBounds.z, maxBounds.z);
transform.position = new Vector3(xPos,yPos,zPos);
}
I am using unity3d horizontal slider to show a character's life like below
But I want to show a vertical bar at the end of filled area like in below image
Any idea? how to achieve this.
You can do this by Lerping the localPosition of your vertical bar.
This would look something like the following:
GameObject verticalBar; //the gameobject you want to use
GameObject player; //Assume this is your play that has the health property
Vector3 startPos; //start position of your total healthbar
Vector3 endPos; //end position of your total healthbar
private void UpdateVerticalBarPosition()
{
float normalized = player.currentHealth / player. maxHealth //this normalizes your current health to be between 0 and 1
if(!float IsNaN(normalized))//(optional) makes sure the value is valid.
{
verticalBar.transform.localPosition = Vector3.Lerp(startPos, endPos, normalized);
}
}
This method will normalize your current HP. meaning that if for example your player has 70 health left of a total 100 health, the normalized value will be 0.7f, or 70% of its total health.
Using this normalized value in a Vector3.Lerp that is clamped between startPos and endPos (here startPos would be the starting position of your total healthbar, so the left side of your grey bar. And endPos the ending positon of your total health bar, so the right side of your grey bar) will put the vertical bar 70% along of the way of your health bar. Which should be the same point where your yellow/orange bar stops.
If you call this method once when hp has changed it will jump to the new value. But if you take damage gradually you can also run it in a loop to make it slide across smoothly.
Alternatively. If you use Unity's Slider component for your healthbar you can also just use the Slider.handleRect. found in the documentations here which would look something like this
Slider healthBar; //the slider used for your healthbar
GameObject verticalBar; // the bar you want displayed at the end of the healthbar
Start()
{
healthBar.handleRect = verticalBar;
}
I solved this, It was pretty simple though!
I just a added the vertical bar texture as child of fill image inside slider and I kept it right aligned.
cheers!
I have this code that instantiates GameObjects at the top of the screen and then they fall down.
float RandX = GetRandomXPos();
float RandY = screenSize.y;
Vector3 ballPos = new Vector3(RandX,RandY,0);
GameObject clone = Instantiate(BallPrefab, ballPos, transform.rotation) as GameObject;
This works fine but it spawn them at the top of the screen so they just blink into existence. I want to spawn them at the top of the screen plus the height of the prefab so that it can appear out of view and then fall down into view.
What is the best way to get that height that I need to offset by?
To get the size of the prefab you need to get the information of the Renderer that the prefab has.
To do this you have to get the component in its hierarchy, you can do this by using GetComponentInChildren<Renderer>()
Once you got the Renderer, you can access the bounds size with renderer.bounds.size
This is a Vector3 which has the dimensions of the object, height being the Y component.
You may have more than one Renderer in a prefab so you will need to get them all with GetComponentsInChildren<Renderer>(). and calculate the sum of all the bounds using bounds.Encapsulate
var renderer = target.GetComponentInChildren<Renderer>();
var height = renderer.bounds.size.y;
In my Unity2D project, I am trying to spawn my sprite on top of each other and across the entire height of the device's screen. For example to give an idea, think of a box on top of each other across the entire device's screen height. In my case, I'm spawning arrow sprites instead of boxes
I already got the sprites spawning on top of each other successfully. My problem now is how to calculate how many sprites to spawn to make sure it spreads across the screen's height.
I currently have this snippet of code:
public void SpawnInitialArrows()
{
// get the size of our sprite first
Vector3 arrowSizeInWorld = dummyArrow.GetComponent<Renderer>().bounds.size;
// get screen.height in world coords
float screenHeightInWorld = Camera.main.ScreenToWorldPoint(new Vector3(0, Screen.height, 0)).y;
// get the bottom edge of the screen in world coords
Vector3 bottomEdgeInWorld = Camera.main.ScreenToWorldPoint(new Vector3(0,0,0));
// calculate how many arrows to spawn based on screen.height/arrow.size.y
int numberOfArrowsToSpawn = (int)screenHeightInWorld / (int)arrowSizeInWorld.y;
// create a vector3 to store the position of the previous arrow
Vector3 lastArrowPos = Vector3.zero;
for(int i = 0; i < numberOfArrowsToSpawn; ++i)
{
GameObject newArrow = this.SpawnArrow();
// if this is the first arrow in the list, spawn at the bottom of the screen
if(LevelManager.current.arrowList.Count == 0)
{
// we only handle the y position because we're stacking them on top of each other!
newArrow.transform.position = new Vector3(newArrow.transform.position.x,
bottomEdgeInWorld.y + arrowSizeInWorld.y/2,
newArrow.transform.position.z);
}
else
{
// else, spawn on top of the previous arrow
newArrow.transform.position = new Vector3(newArrow.transform.position.x,
lastArrowPos.y + arrowSizeInWorld.y,
newArrow.transform.position.z);
}
// save the position of this arrow so that we know where to spawn the next arrow!
lastArrowPos = new Vector3(newArrow.transform.position.x,
newArrow.transform.position.y,
newArrow.transform.position.z);
LevelManager.current.arrowList.Add(newArrow);
}
}
The problem with my current code is that it doesn't spawn the correct number of sprites to cover the entire height of the device's screen. It only spawns my arrow sprites approximately up to the middle of the screen. What I want is for it to be able to spawn up to the top edge of the screen.
Anyone know where the calculation went wrong? and how to make the current code cleaner?
If sprites are rendered via camera mode in perspective and the sprites appear to have varying sizes when displayed on the screen (sprites farther away from the camera are smaller than sprites that are closer to the camera) then a new way to calculate the numberOfArrowsToSpawn value is needed.
You could try adding sprites with a while loop, instead of using a for loop, just continue creating sprites until the calculated world position for the sprite will no longer be visible to the camera. Check to see if a point will be visible in camera by using the technique Jessy provides in this link:
http://forum.unity3d.com/threads/point-in-camera-view.72523/
I think your screenHeightInWorld is really a screenTopInWorld, a point can be anywhere in the space.
You need the relative screen height in world coordinate.
Which is actially the half of the camera frustum size if you use ortographic projection, as you think of it.
float screenHeightInWorld = Camera.main.orthographicSize / 2.0f;
I did not read the rest, but is probably fine, up to you how you implement this.
I'd simply create an arrow method, something like bool SpawnArrowAboveIfFits(), which can call itself iteratively on the new instances.