- Home /
Drag Object along local z-axis. Using WorldToScreenPoint.
I want to drag an object along its local z-axis. Inspired by robertbu's answer on one of my last question I tried to implement the dragging without using RayCasts.
This is the code so far:
private var mainCam : Camera;
private var v3StartPos : Vector3;
private var v2Pivot : Vector2;
private var v2ScreenStartPos : Vector2;
function OnMouseDown(){
mainCam = GameObject.FindWithTag("MainCamera").camera;
v3StartPos = transform.localPosition;
v2Pivot = mainCam.WorldToScreenPoint(transform.position);
v2ScreenStartPos = Input.mousePosition - v2Pivot;
}
function OnMouseDrag(){
var v2T : Vector2 = Input.mousePosition - v2Pivot;
var v3T : Vector3 = v3StartPos;
v3T.z = v3T.z - (v2T.y - v2ScreenStartPos.y);
transform.localPosition = v3T;
}
I have two main problems with this code:
I expected v2Pivot to be in [0, screen.dimension] but the values are negativ(!) something like [-90,-100] even so I can see the object. It is completely visible in my screen.
Dragging the Object in the editor leads to z-axis changes between [0,1]. The
mousePosition
reveals values in [0, screen.dimension]. Hence I need to get themousePosition
relative to thetransform.Position
. Unfortunately I have no idea who to achieve this.Edit
think I was not clear enough. If I move the mouse 1 pixel upwards, the object will be moved 1 unit in z direction. This is way to "fast". The object should always stay beneath the mouse cursor. So you will not lose the object because it is shooting out of your screen.
Thank you for your help!
Thank you for the hint. I am currently trying to figure out, where to use TransformDirection()
. Can you shed some light onto this?
A shoot: Change
v3T.z = v3T.z - (v2T.y - v2ScreenStartPos.y);
transform.localPosition = v3T;
to
transform.localPosition = v3T;
transform.Translate(0,0,-(v2T.y - v2ScreenStartPos.y));
transform.Translate(0,0,2) make the transform to move 2 z-position along its local z-axis
Thank you for the code. Unfortunately the Object still moves way to fast. If I move the mouse 1 pixel upwards the object moves 1 Unity in z direction. How can I get the object to move with the same "speed" as the mouse. So the object will always stay beneath the mouse cursor?
Answer by robertbu · Jan 27, 2013 at 04:31 PM
Getting the object to move in the Z direction as the same speed as Y movement of the mouse I believe to be a difficult problem. Think about the "base" case of a camera facing down the Z axis with an object at 0.0. There would be no way to keep the mouse on the object since the Y value of the object never moves as it travels along the Z axis. Bringing the camera up, changes things, but still the Z movement is heavily dependent on both the angle of view and the perspective. As an object drifts down the Z axis, it size decreases, so the map between Y movement and Z movement is not linear. Over limited distances, it can be fudged by just adding a factor. The code below has a linear factor. You might be able to improve the result by varying the factor by the distance the object is from the camera. Someone who knows a bit more about the math of perspective might give you an idea of what curve to use, or you could just experiment.
private var factor : float = 20.0;
private var v3StartPos : Vector3; // Initial position of object
private var v3DownPos : Vector3; // Initial position of the mouse in world coordinates
private var fZMap : float; // Base Z distance to use in conversion
function OnMouseDown(){
v3StartPos = transform.localPosition;
var v3T : Vector3 = Camera.main.WorldToScreenPoint(v3StartPos);
fZMap = v3T.z;
v3DownPos = new Vector3 (Input.mousePosition.x, Input.mousePosition.y, fZMap);
v3DownPos = Camera.main.ScreenToWorldPoint(v3DownPos);
}
function OnMouseDrag(){
v3T = new Vector3 (Input.mousePosition.x, Input.mousePosition.y, fZMap);
v3T = Camera.main.ScreenToWorldPoint(v3T);
var v3T2 : Vector3 = v3StartPos;
v3T2 = v3StartPos;
v3T2.x = v3T2.x + (v3T.x - v3DownPos.x);
v3T2.z = v3T2.z + (v3T.y - v3DownPos.y) * factor;
transform.localPosition = v3T2;
}
Thank you again for your script. The object doesn't shoot out of the window anymore. In fact it works like a charm.
Facing the problems that come along when using ScreenToWorldPoint
would you suggest to use a ray ins$$anonymous$$d to do the job?
I'm not which problem you are referring to with ScreenToWorldPoint. Any problem with ScreenToWorldPoint that I can think of would also occur with Raycasting. Using On$$anonymous$$ouseDown/Drag/Up is object-centric. That is an object knows how to move itself. Note these methods are not available on touch devices. So which to use mostly depends on your game logic and your target device.