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
Related
I'm trying to instantiate my ballPrefab on click at the cursor's position.
I know that Input.mousePosition only takes the x and y coordinates. However, my camera looks in the direction of x (global) (as you can see here). So I changed x to 0. The problem is that the prefabs spawn at the same y and z position every time, no matter where I left-click.
This is my code.
[SerializeField]
private GameObject ballPrefab;
void Update()
{
Vector3 mousePos = Input.mousePosition;
mousePos = Camera.main.ScreenToWorldPoint(mousePos);
mousePos.x = 0;
if (Input.GetButtonDown("Fire1"))
{
Instantiate(ballPrefab, mousePos, ballPrefab.transform.rotation);
}
}
I searched the internet for like an hour.
What I came across was Cursor.Position, which seems to be old (?), since System.Windows.Forms doesn't exist.
I also tried making the mouse position a new Point , but then I can't convert it to a Vector3.
I also thought of transform.localPosition since my camera is facing the "wrong" direction, but I can't apply transform if I use Input.mousePosition .
Finally, I read about raycasts, but I don't really understand them.
To understand the issue it's best to understand how ScreenToWorldPoint works. Close one of your eyes and look straight ahead and don't move your eye (like a 2D camera). Then extend one of your arms and take your pointer finger and place it on top of something in the distance of your view (like a mouse pointer) but don't move your eye or look directly at it. The ScreenToWorldPoint function works somewhat by taking note of where your finger is on the X and Y axis of your eye's view, but it will also need to know how far out you extended your arm and finger on the Z axis (depth) to make your finger align with what you are pointing at. Like drawing a line from your eye to your finger.
The issue is that Input.mousePosition will return a Vector3 where the Z axis (depth) is 0. That means when you pass it to ScreenToWorldPoint it basically doesn't know how far out you extended your arm and finger. That is like taking your finger and placing it directly on top of your eyeball, but adding very little X or Y so the finger is still pointing at your object. You will get very small X and Y values, and the Z value will be whereever your eyeball (camera) is.
The other issue is that you are manually setting the resulting X value to 0. So X will always be 0, and the Z will always be at the camera's Z position, and the Y value will be very small, all because no depth value was passed to the ScreenToWorldPoint function. This will result in the ballPrefab always ending up in roughly the same location in the world.
So try to give it a depth reference like this:
public float distanceFromCamera = 5f;
public GameObject ballPrefab;
void Update()
{
if (Input.GetButtonDown("Fire1"))
{
Vector3 mousePos = Input.mousePosition;
mousePos = Camera.main.ScreenToWorldPoint(
new Vector3(mousePos.x, mousePos.y, distanceFromCamera));
Instantiate(ballPrefab, mousePos, ballPrefab.transform.rotation);
}
}
It seems you want the ball to always be on the X axis of the world, so another solution is to use the absolute value of the camera's X position (which is the distance the camera is from X = 0) as the depth value.
mousePos = Camera.main.ScreenToWorldPoint(
new Vector3(mousePos.x, mousePos.y,
Mathf.Abs(Camera.main.transform.position.x)));
This will allow you to move your camera in and out (in your case along the X axis) without having to adjust any distanceFromCamera variable.
I want to follow the camera the player along (just the y axis, but this I will look later) for now I have the following problem:
I have a background image in a seperate canvas (World Space) with my Main Camera attached.
Now if I attach a camera follow script (simply transform.position = Player.transform.position) the background image follows.
This results to the following: Everything falls down.
I tried to use another camera but I don't know if I just did it wrong. I have no idea.
as I said, just:
void update()
{
transform.position = Player.transform.position
}
but the code isn't my problem. I expect that the camera follows the player on the y axis (but not 100% just smoothly a bit) but I will look up for that later
I want that the Background doesn't move. Is there another Way to have them background images as a world space, or something I don't know?
void update()
{transform.position = Player.transform.position}
this will make your camera follow your player whatever his direction.
while u didnt mention any details, I expect the reason why everything is falling bec your mainplayer is falling due to physics . and u need to fix this by adding rigibody to your mainplayer and make sure that any thing he walk on also has colliders.
if u want your camera only to follow player on Y axis only , it should be something like this
void update()
{ float y = player.transfor.position.y;
Vector3 newPos = new Vector3(transform.position.x,y,transform.position.z);
transform.position = newPos;
}
and I suggest you cach your transform varaibles too.
lastly about your image that you dont want it to move, just dont attach it to any moving gameobject and set it to static and it should never move at all.
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.
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.
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.