single-direction (mouse) drag Click and drag object at full speed Change the moving direction

To make a small Indie Game like classic unblock game or something similar, the first function we should implete in Unity is to enable users using mouse to ‘drag’ different objects in its specific direction(x-coordinate / y-coordinate).

Classic unblock game:

1
2
3
4
5
6
7
8
9
10
11
12
//the script detect user's mouse behavior and output objects' information when user click them. Note: objects want to be detected must be Collider.
void Update ()
{
if (Input.GetMouseButtonDown (0)) //the very moment when user press the button
{
Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast (ray, out hit)) {
Debug.Log(hit.collider.tag);
}
}
}

GetMouseButtonDown()

The parameter 0 in function GetMouseButtonDown(0) means user pressed the left click, and it returns bool value.
Button:
0 : the left click of mouse
1 : the right click of mouse
2 : the middle click of mouse

Camera.main.ScreenPointToRay()

1. The Camera.main means the main camera (camera which is tagged ‘main’)in current scene.
2. ScreenPointToRay:
 public Ray ScreenpointToRay(Vector3 position);
 Definition: Returns a ray going from camera through a screen point. Resulting ray is in world space.
 Screenspace: Defined in pixels. The bottom-left of the screen is (0,0); the right-top is (pixelWidth,pixelHeight)/(Screen.width, Screen.height).
3. mousePosition:
 public static Vector3 mousePosition;
 Definition: The current mouse position in pixel coordinates.
 Note: Position values < 0 or > (Screen.width,Screen.height) indicate that the mouse cursor is outside of the game window.

Physics.Raycast()

This function has a lot of expression ways. It returns bool True when the ray intersects any collider.
out RaycastHit can store information back from a raycast.
float maxDistance can set your reachable area of a raycast.
int layerMask can selectively ignore Colliders when casting a ray.
QueryTriggerInteraction queryTriggerInteraction allows you to control whether or not Trigger colliders generate a hit, or whether to use the global Physics.queriesHitTriggers setting.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//example
using UnityEngine;
public class ExampleClass : MonoBehaviour
{
void Update()
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, 100))
Debug.DrawLine(ray.origin, hit.point);
}
}

Click and drag object at full speed

The idea used here is very simple. offset records the orignial distance between ScreenToWorldPoint and selected object’s transform. If user moves mouse on screen, the new ScreenToWorldPoint should be add to offset to get the new position of selected object.

Notice that we use bool value drag and function GetMouseButtonUp(0) here to make sure not happen the situation where next time user clicks without selecting object but the value drag and selected_object exist and then make an error.
Reference:
Unity Community-Answer

Note: For most moving Game Object if we want to change the position of it, we usually use Rigidbody.position(Vector 3) instead of Transform.Translate(Vector 3)
Reference: transform.Translate vs rigidbody.MovePosition?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
public class one_way_drag : MonoBehaviour {
private float dist;
private Vector3 distance;
private Vector3 offset;
private Vector3 v3;
private bool drag = false;
private GameObject selected_object;
private Rigidbody drag_rigid;
private Transform toDrag;
// Use this for initialization
void () {
}
// Update is called once per frame
void Update () {
if (Input.GetMouseButtonDown (0)) { //the very moment when user press the button
Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast (ray, out hit)) {
selected_object = hit.transform.gameObject;
drag = true;
toDrag = hit.transform;
dist = hit.transform.position.z - Camera.main.transform.position.z;
v3 = new Vector3 (Input.mousePosition.x, Input.mousePosition.y, dist);
v3 = Camera.main.ScreenToWorldPoint (v3);
offset = toDrag.position - v3; //make the full speed of transform
drag = true;
}
}
if(Input.GetMouseButton(0)) { //while user cliking the button
if (drag){
drag_rigid = selected_object.GetComponent<Rigidbody>();
v3 = new Vector3(Input.mousePosition.x, Input.mousePosition.y, dist);
v3 = Camera.main.ScreenToWorldPoint(v3);
toDrag.position = v3 + offset; //in condition to use full speed
}
}
if (Input.GetMouseButtonUp(0)) { //once user not click the button
selected_object = null;
drag = false;
}
}
}

Change the moving direction

The idea to make sure objects are moved in its specific direction(x/y), is that, add tag to different objects, like ‘Vertical’ or ‘Horizontal’. Then use a if function to make sure which way to move it, and then change the moving function a little bit.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
using System.Collections.Generic;
using UnityEngine;
public class one_way_drag : MonoBehaviour {
private float dist;
private Vector3 distance;
private Vector3 offset;
private Vector3 v3;
private bool drag = false;
private GameObject selected_object;
private Rigidbody drag_rigid;
private Transform toDrag;
// Use this for initialization
void () {
}
// Update is called once per frame
void Update () {
if (Input.GetMouseButtonDown (0)) { //the very moment when user press the button
Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast (ray, out hit)) {
if (hit.transform.gameObject.tag == "vertical" || hit.transform.gameObject.tag == "horizontal") { //tag the selected object
selected_object = hit.transform.gameObject;
drag = true;
toDrag = hit.transform;
dist = hit.transform.position.z - Camera.main.transform.position.z;
v3 = new Vector3 (Input.mousePosition.x, Input.mousePosition.y, dist);
v3 = Camera.main.ScreenToWorldPoint (v3);
offset = toDrag.position - v3; //make the full speed of transform
drag = true;
}
}
}
if(Input.GetMouseButton(0)) { //while user cliking the button
if (drag){
drag_rigid = selected_object.GetComponent<Rigidbody>();
v3 = new Vector3(Input.mousePosition.x, Input.mousePosition.y, dist);
v3 = Camera.main.ScreenToWorldPoint(v3);
if (toDrag.tag == "vertical")
drag_rigid.position = new Vector3(toDrag.position.x, toDrag.position.y, v3.z + offset.z);
if (toDrag.tag == "horizontal")
drag_rigid.position = new Vector3(v3.x + offset.x, toDrag.position.y, toDrag.position.z);
}
}
if (Input.GetMouseButtonUp(0)) { //once user not click the button
selected_object = null;
drag = false;
}
}
}