0
\$\begingroup\$

How is it possible to get a cursors X and Y Location relative to the scene planes rather than using co-ordinates based upon pixels of screen height and width?

I have the start of a very basic game, picture with a few physical aids shown below.

I want to find out how far away the cursor is on the X and Y axis from an object in the scene. The Z axis is irrelevant due to the nature and orientation of the game, so z = 0. (Note that in Unity, the Y axis is vertical)

Basically, the distance of the cursor from the cube on the X Axis upon clicking will define the power of an action.

Because of this. I want to get the cursor X position relative to the 0 point of the scene ( or the object ), not relative to the bottom left corner of the screen.

I could then use Vector3.Magnitude() to get the distance.

How is this possible?

Image showing scene and visual aids

\$\endgroup\$
1
\$\begingroup\$

Since you're aiming at a known constant plane, you can do this without physics raycasting.

Vector3 GetCursorPositionOnScenePlane(float zValue = 0f)
{
    Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);

    float depth = zValue - ray.origin.z;
    float zDirection = ray.direction.z;

    if(Mathf.Approximately(zDirection, 0f) // Ray parallel to XY plane.
       || depth * zDirection < 0f)         // Ray looking away from plane.
    {
        // Error - this ray can't see the plane!
        // This won't happen if your camera is looking at the scene plane.
        return new Vector3(float.NaN, float.NaN, float.NaN);
    }

    // Calculate how many times we need to travel along the direction vector
    // from the ray's origin before hitting our desired zValue:
    float scale = depth/zDirection;

    return ray.origin + scale * ray.direction;
}

Note that this differs from Camera.ScreenToWorldPoint in that the zValue here is a z position in world space, so your outputs are always in a world-XY-aligned plane. ScreenToWorldPoint's z is a distance from the camera, so if the camera is rotated then the plane of its outputs may be tilted relative to the world XY plane.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Thanks DM, I'll have to try this - it's a lot cleaner and makes more sense to me than the other script. \$\endgroup\$ – Panomosh Feb 25 '16 at 13:25
  • 1
    \$\begingroup\$ @Panomosh I've made a quick edit so the script works for arbitrary z values. \$\endgroup\$ – DMGregory Feb 25 '16 at 13:50
1
\$\begingroup\$

It is possible and Unity documentation is very helpful in this matter. First you need a ray to raycast from mouse position, the documentation for mouse position provides an example how to get a ray from mouse position:

public class ExampleClass : MonoBehaviour {
    void Update() {
        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
    }
}

because you are not interested in all of the objects(just the plane*), following to documentation of Physics.Raycast will tell you all possible overloads, one of them having a layer mask. You are also interested in position, so choosing an overlaod with RaycastHit and following documentation to RaycastHit tells you there is a ".position":

using UnityEngine;
using System.Collections;

public class ExampleClass : MonoBehaviour {
    void Update() {
        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
        RaycastHit hit;
        int maskOfPlane = 1 << planeLayer;
        if (Physics.Raycast(ray, out hit, maskOfPlane)) {
            //one of coordiantes being always zero for aligned plane
            var position = hit.position;//this is relative to 0,0,0
            var relativePosition = other.transform.position - position; //relative to a gameObject other
        }
    }
}

*literally place an invisible plane in the world aligned with your games logical plane and move it to a custom layer, you will need to set the mask against it.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ This is perfect, thank you wondra. I Appreciate the effort. \$\endgroup\$ – Panomosh Feb 25 '16 at 12:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.