Moving a object along a plane?

I have a script casts a ray from where the mouse has clicked and attaches the object to the origin of the ray. However, when I move the mouse I want the object to move along the X and Z axis( along a plane ) instead of along the Y axis. How can I do that?

Thanks

Maybe a photo will explain better.

Here’s the code:
function OnMouseDown () {

    if(!selected)
    {
        selected = true;
    }

    else
    {
        selected = false;
    }
}

function Update () {

    if(selected == true)
    {
        FollowCursor();
    }
}

function FollowCursor()
{
    var ray : Ray = Camera.main.ScreenPointToRay(Input.mousePosition);
    var point : Vector3 = ray.origin + (ray.direction * distance);
    obj.transform.position = point;
}

You should probably look at some of the examples for Physics.Raycast() and, for a more closely connected example for what you’re doing, Input.mousePosition.

An easy aspect to overlook when using the conversions between screen space and world space (among others) with the camera is the lack of depth.

When you get the mouse position, the value is a Vector3, yet it generally provides no significant/usable data on the Z-axis. As a result, converting from the mouse position on screen to a world point can do so relative to the camera’s perspective, but will only be able to utilize the depth assigned to it manually.

To compensate for that, you can instead fire a Raycast. This can be used to hit at the position of the mouse cursor on the screen – Then you have an accurate point of reference for where to move to.

function FollowCursor()
{
	var ray : Ray = Camera.main.ScreenPointToRay	(Input.mousePosition);
	var hit: RaycastHit;
	if(Physics.Raycast(ray, hit, 100))
	{
		var point : Vector3 = hit.point;
		obj.transform.position = point; // No smoothing
	}
	obj.transform.position = point;
}

If you don’t make any other changes first, something rather silly will happen. The Raycast will hit the ground and the box will move to a position where it’s halfway embedded in the ground. Then, on the next frame, the Raycast will instead hit the box and the box will move to where the cursor was aimed at the box. On the next frame, the box will move further towards the screen. This will occur until the box passes through the camera, clearing the way for the Raycast to hit the ground again.

Something needs to be done about that.

Well, there are two relatively easy options to choose from to make this work smoothly:

  1. Rather than using Physics.Raycast, use Collider.Raycast(). If the Raycast is linked directly to the ground, then it will be unable to hit anything else, but this will keep the box from being a potential Raycast target.

  2. Put the box on its own layer and have the Raycast ignore that layer (by adding another argument into the overloaded function). This is the potentially-more-versatile option. It won’t be limited to a single object’s collider like option 1, but it will require more care to prevent the raycast from hitting any unintended targets.

In theory, you actually don’t have to raycast at all to move along a imaginary plane. Just make sure you set the distance in your calculation to the correct value.

If your plane is y up like in your image, all you’d have to do is change the “distance” in your calculation to ((ray.origin.y - plane.y) / ray.direction.y) and you are done :stuck_out_tongue: (except if ray.direction.y is 0, but in theory you should prevent such values by placing your camera correctly)

Another way to do this is to use Plane.Raycast. Added advantage is that this also works for planes that don’t have y-up as their normal and it catches the times when the ray is moving parallel to the plane (the ray.direction.y == 0 in the example above) or the ray is moving away from your plane by simply returning false rather then true, like so:

Plane plane = new Plane(Vector3.up, Vector3.zero);
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
float distance;
if (plane.Raycast(ray, out distance))
{
    Vector3 pointalongplane = ray.origin + (ray.direction * distance);
}

Using Ray.GetPoint like in the example looks even fancier, but yea, does the same :stuck_out_tongue:

I am using the same code and it is exactly what I need to do but is there a way to make it so wherever you click on the object it will drag from that point instead of in the center?