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:

  1. 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.
  2. 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 the mousePosition relative to the transform.Position. Unfortunately I have no idea who to achieve this.


I 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!

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;