I am having trouble getting good results doing something that seems as though it should be pretty simple - use the mouse drag an object across a plane.
I am using OnMouseDrag but the object is not keeping up with the mouse. Is there a sample script somewhere on how to do this right?
Thanks
are you slerping the objects position? setting it simply to equals instead might do it.
Well, depending on what screen res you’re using and what your viewing angle is the odds are very good that a unit of mouse drag isn’t going to equal a single unit in the game world. I don’t think it’s ever going to be possible to get a 1-to-1 match unless you use screen traces from the mouse into the world or something like that.
You could try putting the code in LateUpdate instead of Update.
Intuitively it seems simple, but programatically it’s actually not that simple. I’ve used raycasting to a plane to get the distance, but a more “correct” solution can be found in Carsten’s code here.
–Eric
Thanks for all of your responses. I am trying Carsten’s script and have been convinced by it that dragging an object with the mouse is not so simple as I thought it should be.
Two problems I am having:
- I need the object’s “Z distance from camera” to be decided by gravity so that the object stays on the plane and
- I need the object to still interact with other objects so that it doesn’t just go right through things but stops when it meets and obstacle
I have messed with the script some to try to do this, but my mind is having trouble with just understanding that one variable - “p” - can hold the x, y and z axis the way it does.
Is there a way to do the above (1 2) with Carsten’s script?
Here it is for easy reference:
var wantedZDistanceFromCamera = 5.0;
function OnMouseDrag () {
var mainCamera = FindCamera();
// Position on the near clipping plane of the camera in world space
var p = mainCamera.ScreenToWorldPoint(Vector3(Input.mousePosition.x, Input.mousePosition.y, 0));
// Position relative to the eye-point of the camera
p -= mainCamera.transform.position;
// A relative position at the wanted z distance from the camera
var currentZDistanceFromCamera : float = Vector3.Dot(mainCamera.transform.forward, p );
p *= wantedZDistanceFromCamera / currentZDistanceFromCamera;
// The position in world space
p += mainCamera.transform.position;
transform.position = p;
}
function FindCamera ()
{
if (camera)
return camera;
else
return Camera.main;
}
I have made a new version of the script. It makes some assumptions about what you are trying to do.
- The direction you don’t want things to move, is the y-axis
- You are more or less “looking down” on the plane. It doesn’t have to be straight down. Just more down than up.
This should solve your first problem. About the collision stuff, I hope someone less sleepy than me can help you do that. It has to do with attaching colliders to objects, and finding the proper way to reach to collisions. For example the hook functions OnCollisionEnter/OnCollisionStay
Hope the script works for you. It works on my machine
// Which way is "Up" ? We don't want to be moving "up" or "down"
var planeNormal : Vector3 = Vector3( 0, 1, 0 );
var currentProjectedOnPlaneNormal : float;
var cameraProjectedOnPlaneNormal : float;
var wantedDistanceFromCamera : float;
var pOnPlaneNormal : float;
private var rememberedYPos: float;
function OnMouseDown () {
// An extra hack: If Up is (0,1,0), then we remember the y-coordinate, so we don't change it
rememberedYPos = transform.position.y;
}
function OnMouseDrag () {
var p: Vector3;
var mainCamera = FindCamera();
// Position on the near clipping plane of the camera in world space
p = mainCamera.ScreenToWorldPoint(Vector3(Input.mousePosition.x, Input.mousePosition.y, 0));
// Position relative to the eye-point of the camera
p -= mainCamera.transform.position;
currentProjectedOnPlaneNormal = Vector3.Dot( planeNormal, transform.position );
cameraProjectedOnPlaneNormal = Vector3.Dot( planeNormal, mainCamera.transform.position );
wantedDistanceFromCamera = cameraProjectedOnPlaneNormal - currentProjectedOnPlaneNormal;
pOnPlaneNormal = Vector3.Dot( planeNormal, p );
p *= wantedDistanceFromCamera / -pOnPlaneNormal;
p += mainCamera.transform.position;
transform.position = p;
// If we know that the object should only move in its x,z coordinates, we can
// make sure we don't drift slowly off the plane by doing this:
transform.position.y = rememberedYPos;
}
function FindCamera ()
{
if (camera)
return camera;
else
return Camera.main;
}
Thank you, Carsten! Will this make my game start growing trees, too? You know, it wasn’t so long ago, I was impressed with just making an object move across a surface using scripting in Unity. I’ve come a little bit beyond that but there’s still a whole other world out there well beyond my ken. Thanks for a glimpse of it…
I’ll try this script out soon.
Nah, you would just use them for shooting arrows at, anyway.
Yep, as far as dragging it on a plane it works perfect now. I’ll see what I can come up with for adding collsion reactions. Thanks again!
In 2023 for those who are still searching:
private void OnMouseDrag()
{
var dragPlane = new Plane(dragPlaneTransform.up, dragPlaneTransform.position);
Ray ray = playerCamera.ScreenPointToRay(Input.mousePosition);
float enter;
if (dragPlane.Raycast(ray, out enter))
{
//Get the point that is clicked
Vector3 hitPoint = ray.GetPoint(enter);
//Move your cube GameObject to the point where you clicked
transform.position = hitPoint;
}
This worked perfectly for me, thank you