Draw a Rect using GUI.DrawTexture on exactly gameobject's position Unity - unity3d

I have to use the "GUI.DrawTexture(new Rect..." function to draw a rectangle on my screen(actually, it's a gradient GUI bar i got from https://www.assetstore.unity3d.com/en/#!/content/19972, but deep inside it's just a rectangle). I want to do it right beside a gameobject i have on my screen.
The problem is: It seems like rectangle's coordinates are not the same as a gameobjects coordinates(i have searched online and i guess it's true). I have tried the function below to convert a gameobject's position to a rectangle's coordinates but still no luck:
public Vector2 WorldToGuiPoint(Vector2 position)
{
var guiPosition = Camera.main.WorldToScreenPoint(position);
guiPosition.y = Screen.currentResolution.height - guiPosition.y;
return guiPosition;
}
My best strike was when i did this:
Vector3 gameObjectsPosition = Camera.main.WorldToScreenPoint(gameObject);
And then when i wanted to draw the rectangle i did:
GUI.DrawTexture(new Rect(gameObjectsPosition.x, Screen.height - gameObjectsPosition.y, Background.width * ScaleSize, Background.height * ScaleSize), Background);
But still, the Rect isn't on the exact gameObject's position. It's x is right but y don't and when i searched the internet, they said I only had to do the "Screen.height - gameObjectsPosition.y" when drawing the Rect. It didn't work for me, the y is still wrong.
What should i do to create a rectangle that's like, right beside a current gameobject on screen (like, if the gameobject's position is x = -401 and y = -80, i want it on y=-80 and x=-300)

You need to use Screen.height instead of
Screen.currentResolution.height
using UnityEngine;
using System.Collections;
public class GuiPosition : MonoBehaviour
{
public Vector2 WorldToGuiPoint(Vector3 GOposition)
{
var guiPosition = Camera.main.WorldToScreenPoint(GOposition);
// Y axis coordinate in screen is reversed relative to world Y coordinate
guiPosition.y = Screen.height - guiPosition.y;
return guiPosition;
}
void OnGUI()
{
var guiPosition = WorldToGuiPoint(gameObject.transform.position);
var rect = new Rect(guiPosition, new Vector2(200, 70));
GUI.Label(rect, "TEST");
}
}
I've just tested attaching that MonoBehaviour to a Cube GameObject and it works

Related

Unity3D - Move camera perpendicular to where it's facing

I'm adding the option for players to move the camera to the sides. I also want to limit how far they can move the camera to the sides.
If the camera was aligned with the axis, I could simply move around X/Z axis and set a limit on each axis as to how far it can go. But my problem is that the camera is rotated, so I'm stuck figuring out how to move it and set a limit. How could I implement this?
using UnityEngine;
[RequireComponent(typeof(Camera))]
public class CameraController : MonoBehaviour
{
Camera cam;
Vector3 dragOrigin;
bool drag = false;
void Awake()
{
cam = GetComponent<Camera>();
}
void LateUpdate()
{
// Camera movement with mouse
Vector3 diff = (cam.ScreenToWorldPoint(Input.mousePosition)) - cam.transform.position;
if (Input.GetMouseButton(0))
{
if (drag == false)
{
drag = true;
dragOrigin = cam.ScreenToWorldPoint(Input.mousePosition);
}
}
else
{
drag = false;
}
if (drag)
{
// Here I want to set a constraint in a rectangular plane perpendicular to camera view
transform.position = dragOrigin - diff;
}
}
}
Transform in Unity comes with a handy Transform.right property, which regards the object's rotation. To move your camera sideways you could further utilize Lerp to make the movement smooth.
transform.position += transform.right * factor
moves an object to the right.
Use factor to adjust the desired distance and by doing so you can also set limits. Negative factor would mean moving left by the way:) Hope that helps!
It can be tricky to deal with constraints on rotated objects. The math behind this includes some vector/rotation math to figure out the correct limits relative to the object's orientation, and whether you've exceeded them.
Luckily though, Unity gives you some shortcuts to skip this math: Transform.InverseTransformPoint() and Transform.TransformPoint()! These two methods allow you to transform a point in world space into a point in local space, and vice versa.
That means that no matter how your camera is oriented, you can interpret a position from the orientation of the camera - and with just a couple extra steps, your X/Z constraints are usable because you can calculate X/Z from the camera's point of view.
Let's try to adapt your current script to use this:
using UnityEngine;
[RequireComponent(typeof(Camera))]
public class CameraController : MonoBehaviour
{
// Set the X and Z values in the editor to define the rectangle within
// which your camera can move
public Vector3 maxConstraints;
public Vector3 minConstraints;
Camera cam;
Vector3 dragOrigin;
bool drag = false;
Vector3 cameraStart;
void Awake()
{
cam = GetComponent<Camera>();
// Here, we record the start since we'll need a reference to determine
// how far the camera has moved within the allowed rectangle
cameraStart = transform.position;
}
void LateUpdate()
{
// Camera movement with mouse
Vector3 diff = (cam.ScreenToWorldPoint(Input.mousePosition)) - cam.transform.position;
if (Input.GetMouseButton(0))
{
if (drag == false)
{
drag = true;
dragOrigin = cam.ScreenToWorldPoint(Input.mousePosition);
}
}
else
{
drag = false;
}
if (drag)
{
// Now, rather than setting the position directly, let's make sure it's
// within the valid rectangle first
Vector3 newPosition = dragOrigin - diff;
// First, we get into the local space of the camera and determine the delta
// between the start and possible new position
Vector3 localStart = transform.InverseTransformPoint(cameraStart);
Vector3 localNewPosition = transform.InverseTransformPoint(newPosition);
Vector3 localDelta = localNewPosition - localStart;
// Now, we calculate constrained values for the X and Z coordinates
float clampedDeltaX = Mathf.Clamp(localDelta.x, minConstraint.x, maxConstraint.x);
float clampedDeltaZ = Mathf.Clamp(localDelta.z, minConstraint.z, maxConstraint.z);
// Then, we can use the constrained values to determine the constrained position
// within local space
Vector3 localClampedPosition = new Vector3(clampedDeltaX, localDelta.y, clampedDeltaZ)
+ localStart;
// Finally, we can convert the local position back to world space and use it
transform.position = transform.TransformPoint(localConstrainedPosition);
}
}
}
Note that I'm somewhat assuming dragOrigin - diff moves your camera correctly in its present state. If it doesn't do what you want, please include details on the unwanted behaviour and we can sort that out too.

i want to make my weapon follow the cursor but Within limits of a circle plzzz helpp || unity2d

i want to make my weapon follow the cursor but Within limits of a circle plzzz helpp , i use this code and it works but the circle had a radius of 2 at (0,0) , i want to control the position of the circle to prevent making the weapon stuck in circle in (0,0) , help help
void Update()
{
mousePos = cam.ScreenToWorldPoint(Input.mousePosition);
rb.MovePosition(Vector2.ClampMagnitude(mousePos ,2.0f));
}
public Transform CentreOfCircle;
private void Update()
{
Vector2 targetPosition = cam.ScreenToWorldPoint(Input.mousePosition);
rb.MovePosition(Vector2.ClampMagnitude(targetPosition - (Vector2)CentreOfCircle.position,Radius)+(Vector2)CentreOfCircle.position);
}
Here CentreOfCircle is the transform of the centre of the circle.

Rotate an object around a point in unity

I'm new to Unity. So just for an experiment, I want to create a canon by attaching a rectangle to a circle and when the up arrow key is pressed, the canon change firing angle. So I have a rectangle object that is a sub object of a circle. And then I created a script in C# for the circle object.
Here is the codes that I have:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
private float rotation = 0f;
private float timeValue = 0.0f;
public GameObject wheele;
private float xMin = -1.0f, xMax = 1.0f;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.UpArrow))
{
if (rotation >= -90)
transform.Rotate(new Vector3(0.0f, 0.0f, rotation));
rotation -= 2;
Mathf.Clamp(rotation, -90.0f, 0);
}
if(Input.GetKeyDown(KeyCode.DownArrow))
{
if (rotation >= -90)
transform.RotateAround(wheele.transform.position, Vector3.up,20);
rotation += 2;
Mathf.Clamp(rotation, -90.0f, 0);
}
}
}
I tried both transform. Rotate method, but it rotate around the center of the rectangle. But we need the rectangle to rotate with the axis, the center of the circle.
You're asking how to get the pivot point changed, right? Make an empty game object and drag the cannon under it to make it a child, then drag the cannon to a point which you think is fine and rotate the empty game object instead of the cannon, which pretty much just changes the pivot point
There are two main ways.
Update your model to set the pivot point exactly where you want it to rotate. This is how you would do this using blender. This would require you to actually create a model for the canon though (even if it's as simple as the one you've used Unity primitives for)
Create a parent GameObject, and rotate it instead. You can offset the cannon inside this GameObject, to compensate for the pivot point set on the model.

Unity why does my object rotate exactly the same around the y axis in both Space.Self and Space.World?

So I was told that Space.Self rotates around local coordinates and Space.World around global coordinates. So I created a small little project and script in unity to verify. However, they both seem to rotating the same way. Is there something I'm doing wrong?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Spin : MonoBehaviour {
public bool isSpinOnSelf = true;
public bool isSpinOnWorld = false;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
if(isSpinOnSelf)
transform.Rotate(0,3f,0, Space.Self);
if(isSpinOnWorld)
transform.Rotate(0, 3f, 0, Space.World);
}
}
It is because the object's Y axis is still aligned with the world's Y axis.
You're spinning around the same axis. If you rotated the object so that its Y axis was horizontal, you would notice a difference between the two. In local space the object would appear to "roll" whereas in world space it would still rotate "sideways".

Unity - Limit Camera Movement XY axis

I have the following code which works really well for scrolling map using the draggable mouse. I am trying to define limits so that I cannot scroll too far in either the x or y co-ordinates. I've seen various examples of code, such as:
"transform.position.x = Mathf.Clamp(-100, 100);" though have not been able to incorporate it into the code. I am a bit of a beginner to all this and have just done a 2D tutorial animating zombies and have a camera that can scroll, but would like to add limits to how far it can scroll in any given directions.
Thanks heaps
Adam
using UnityEngine;
using System.Collections;
public class ViewDrag : MonoBehaviour {
Vector3 hit_position = Vector3.zero;
Vector3 current_position = Vector3.zero;
Vector3 camera_position = Vector3.zero;
float z = 0.0f;
// Use this for initialization
void Start () {
}
void Update(){
if(Input.GetMouseButtonDown(0)){
hit_position = Input.mousePosition;
camera_position = transform.position;
}
if(Input.GetMouseButton(0)){
current_position = Input.mousePosition;
LeftMouseDrag();
}
}
void LeftMouseDrag(){
// From the Unity3D docs: "The z position is in world units from the camera." In my case I'm using the y-axis as height
// with my camera facing back down the y-axis. You can ignore this when the camera is orthograhic.
current_position.z = hit_position.z = camera_position.y;
// Get direction of movement. (Note: Don't normalize, the magnitude of change is going to be Vector3.Distance(current_position-hit_position)
// anyways.
Vector3 direction = Camera.main.ScreenToWorldPoint(current_position) - Camera.main.ScreenToWorldPoint(hit_position);
// Invert direction to that terrain appears to move with the mouse.
direction = direction * -1;
Vector3 position = camera_position + direction;
transform.position = position;
}
}
What exactly is the error you are getting? I imagine it is something along the lines of being unable to modify the return value of position because it is not a variable.
If this is the case, you should however be able to set the whole position vector at once. So try something along the lines of this:
var pos = transform.position;
transform.position = new Vector3(
Math.clampf(pos.x, -100, 100),
Math.clampf(pos.y, -100, 100),
pos.z
);
You may need to swap around clamping Y and Z, depending on how you are using them.