Positioning a Gameobject to stay in screen center always - c#

I'm trying to position a gameobject to stay at the center of the screen always. I'm using the following code to do so,
sphere.SetActive(true);
Vector3 lookAtPosition = FirstPersonCamera.ScreenToWorldPoint(new Vector3(Screen.width / 2, Screen.height / 2, FirstPersonCamera.nearClipPlane));
sphere.transform.position = lookAtPosition;
But for some reason, the gameobject is not visible at all with the above code.
So, I tried to raycast it and make it visible.
Following is the corresponding code,
TrackableHitFlags raycastFilter = TrackableHitFlags.PlaneWithinPolygon | TrackableHitFlags.FeaturePointWithSurfaceNormal;
TrackableHit hit;
if (Frame.Raycast(screenCenter.x, screenCenter.y, raycastFilter, out hit))
{
var pose = hit.Pose;
sphere.SetActive(true);
sphere.transform.position = pose.position;
sphere.transform.up = pose.up;
}
The gameobject shows up occasionally with the above code but it is not centered exactly to the screen and it is not showing up forever. How can I be able to sort it out?

It could be that your object is on top of the camera and outside in its field of view
A problem on its sorting layer
A screenshot of your inspector and scene window might help.

The easiest way to do it is to use the following code (this is an example code for ARCore SDK in Android Studio):
static const Pose oneMeterAway = Pose.makeTranslation(0, 0, -1);
objectPose = camera.getPose().extractTranslation().compose(oneMeterAway);
And then you need to update it every frame.
Hope this helps.

Related

Display speed of a unity vuforia tracking target

I just finished a Vuforia Unity AR project which successfully tracks a target and moves a unity object.
I have done this using AR camera prefab and ImageTrack prefabs.
I have added a 3d sphere with the ImageTrack object. Upon detecting a marker, the sphere is displayed and faithfully follows target where ever it goes.
I want to display the position or speed of this moving sphere which appears and follows the target.
To start with that I have attached a gui textbox with sphere with screenoverlay property.
I set transform.position to this text box and it shows the initial coordinates of ImageTrack when run. As the sphere moves upon marker moving, I want the current position of the sphere to be displayed.
Now it just shows initial position of the ImageTrack even though I placed the code under update(){}
I need latest current position because I need to calculate velocity, acceleration of this moving sphere.
Any help plz
For anyone who may come here, the following code works for me:
private void Update()
{
float x = Camera.main.WorldToScreenPoint(transform.position).x / Screen.width;
float y = Camera.main.WorldToScreenPoint(transform.position).y / Screen.height;
var tString = "x = " + System.Math.Round(x, 4);
var tString2 = "y = " + System.Math.Round(y, 4);
winText.text = tString;
win2Text.text = tString2;
}

How to get proper Z position of a gameObject when using ScreenToWorldPoint?

I thought I previously had a solution to the problem but it seems that it isn't working as well as it should. Basically, I want to move a gameObject in 3D using the mouse while keeping the Z position the same. If I click and drag the gameObject, it should follow the cursor around without changing the depth of its position.
The code that I had was this:
screenSpace = Camera.main.WorldToScreenPoint(transform.position);
mousePosition = new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenSpace.z);
mouseInWorld = Camera.main.ScreenToWorldPoint(mousePosition);
This worked fairly well, but the depth changed ever so slightly every time I moved the object. Why doesn't Unity work if I just do:
mousePosition = new Vector3(Input.mousePosition.x, Input.mousePosition.y, gameObject.transform.position.z);
There are a number of potential causes for this, but the most common would be there's a Rigidbody or Collider enabled that is interacting in some form with the environment that is causing the target object to move.
Try and set the mousePosition as 0:
mousePosition = new Vector3(Input.mousePosition.x, Input.mousePosition.y, 0);
If this works fine, then there is some form of interference either via the Physics system or another component etc that is changing the Z position.
Bear in mind that manually modifying an objects position depends heavily on when you update it.
Feel free to update me with more information if this is not the case, and I'll try to get back to you.

Unity - Camera ScreenToWorldPoint returning odd values

The main camera's output is set to a render texture, which is applied to a material, which is applied to a quad that's scaled up to 128x72. The secondary camera is set to only see what is rendered to the child quad, who has the material with the render texture on it.
However Camera.main.ScreenToWorldPoint(Input.mousePosition) is returning values that aren't even close to the GameObject. I.E. The GameObject is instantiated at (0, 0, 0), and hovering over it shows the mouse at (307, 174). Moving the Rotating Object to the right edge of the screen will only return an x position of 64 (half of the 128px wide quad) so I'm not sure where the 300+ is coming from. Not sure if the quad/camera set up is responsible for this.
EDIT: Using a single orthographic camera, all properties the same except for using a render texture, instead of the setup I have now results in accurate ScreenToWorldPoint output.
The Input.mousePosition property will only return the x and y axis of the mouse position in pixels.
ScreenToWorldPoint requires the z axis too which Input.mousePosition doesn't provide. The z-axis value supposed to be the nearClipPlane of the camera. It will give you a position that's right in front of the camera.
Depending on the size of the 3D object you want to instantiate where mouse button is pressed, you will need to apply an offset to it to make it totally visible to the screen. For a simple cube created in Unity, an offset of 2 is fine. Anything bigger than that, you will need to increase the offset.
Below is a complete example of how to properly use ScreenToWorldPoint with Camera.nearClipPlane and an offset to instantiate a 3D object where mouse is clicked:
public GameObject prefab;
public float offset = 2f;
void Update()
{
if (Input.GetMouseButtonDown(0))
{
Camera cam = Camera.main;
Vector2 mousePos = Vector3.zero;
mousePos.x = Input.mousePosition.x;
mousePos.y = Input.mousePosition.y;
Vector3 worldPoint = cam.ScreenToWorldPoint(new Vector3(mousePos.x, mousePos.y, cam.nearClipPlane + offset));
Instantiate(prefab, worldPoint, Quaternion.identity);
}
}
You may not be calling the Camera.ScreenToWorldPoint method correctly. In particular, the z position of the screen position parameter that's passed to this method should be defined as world units from the camera. See the Unity documentation on Camera.ScreenToWorldPoint.
Instead of Camera.main.ScreenToWorldPoint(Input.mousePosition), I think this is the correct way to call Camera.ScreenToWorldPoint:
var cameraPosition = Camera.main.transform.position;
// assuming `transform` is the transform "Virtual Screen Quad"...
float zWorldDistanceFromCamera = transform.position.z - cameraPosition.z;
var screenPoint = new Vector3(Input.mousePosition.x, Input.mousePosition.y, zWorldDistanceFromCamera);
var worldPoint = Camera.main.ScreenToWorldPoint(screenPoint);
Debug.LogFormat("mousePosition: {0} | zWorldDistanceFromCamera: {1} | worldPoint: {2}",
Input.mousePosition,
zWorldDistanceFromCamera,
worldPoint.ToString("F3"));
(If this isn't working, could you update your question or reply to this post with a comment with details showing the values that are logged at each step?)
I was just struggling with this problem and this question helped me find the answer, so thank you for posting it!
The issue has nothing to do with the z axis or how you're calling Camera.ScreenToWorldPoint. The issue is that the camera you're calling it on is rendering to a RenderTexture, and the dimensions of the RT don't match the dimensions of your game window. I wasn't able to find the implementation of the method in the reference source, but whatever it's doing is dependent on the resolution of the RenderTexture.
To test this, click the stats button in the game window to display the game window's screen size. The coordinates you get will match the ratio between that and the RenderTexture resolution.
Solutions:
Don't call this method on a camera targeting a rendertexture, either target the screen (none) or create a child camera that matches the position of the camera you need
Match the RT resolution to the screen. Obviously this may have performance implications, or cause issues if the screen size changes.
Don't use Camera.ScreenToWorldPoint. Depending on the use case, using a raycast may be simpler or more reliable.
Since using a default camera was returning the correct values, I simply added another one to detect the mouse position independent of the render texture/quad setup.

Get mouse position in world space

I'm making a game using Unity and I have a little issue, I need to know the mouse position in world space, for that I try to set a GameObject at the mouse position using this code :
Vector3 p = Input.mousePosition;
Vector3 pos = Camera.main.ScreenToWorldPoint( p);
testGameObject.transform.position = pos;
It works like a charm in Editor but in exe / apk, the GameObject dosn't follow the mouse:
Example 1
Example 2
The GameObject that is supposed to follow the mouse is the "1" inside a circle
If it's works in editor like a charm, then it should in build to.
I see it already working in build, maybe what you want is to exactly place yor object to match the screen click point, but your object is far too close to the camera so that you can't see it.
maybe there's a problem with the depth of the position from the camera.
try adding something like
Vector3 p = Input.mousePosition;
p.z = 20;
Vector3 pos = Camera.main.ScreenToWorldPoint(p);
testGameObject.transform.position = pos;
To add depth to the mouse position. try to change 20 to -20 if it's still doesn't work

Unity Cube gameobject Transform position not changing

I want to transform the position of the bottom wall. The bottom wall is a 3D cube used for collision. Here is a picture of the cube and properties.
On the right of the image you can see a property bar called transform. I want to access that through a script and change the position. Here is the code I am trying to do that with.
void Start () {
GameObject bottomWall = GameObject.Find("Bottom");
Bottom bottomScript = bottomWall.GetComponent<Bottom>();
bottomScript.wallPos.y = -Camera.main.orthographicSize * 1000;
bottomWall.transform.position.Set(1000, 100, 1000);
bottomWall.GetComponent<Transform>().position.Set(100, 100, 100);
}
Nothing happens when I do this. I can't seem to do it, any help with this is extremely appreciated.
Transform.position returns a copy of a Vector3 instead of the reference. So modifying the copy won't affect the original Vector3 position.
Replace bottomWall.transform.position.Set(1000, 100, 1000);
with
bottomWall.transform.position = new Vector3(100, 100, 100);
Not related to your problem:
Since Bottom is a child of Walls, it is better to use Walls/Button in your Find function as that will tell Unity to look for the Bottom GameObject only under Walls hierarchy. This is fast when you have too many GameObjects in the scene.
So use GameObject bottomWall = GameObject.Find("Walls/Bottom");
Is it the child of another Game Object? Could try gameObject.transform.localPosition

Categories