Drag a Specific GameObject around the screen in a 2.5 sidescroller

I have a 2.5d Sidescroller and I need to find a way to drag a specific platform with my mouse.

(I don’t want it to be a Rigidbody.)

I also need the platform only to be drag-able along 2 axis (x,y).

First, a rigidbody is needed if you want to move an object and want that other objects can interact with it. If you set the rigidbody to `isKinematic` it can only be moved by a script. If the platform isn't moving it's like there's no rigidbody, but if you move it (draggin or auto-moving like an elevator) you need a rigidbody. Otherwise the platform can pass through everything.

Now to your problem:

It might be a bit complicated for complete beginners but i would use the Plane class. Just create an infinite plane through your 0 z-level so you can raycast against it. That way you get the point on this plane and that’s “almost” all you need :wink:

You didn't tell us what language you're using so i use my preferred one (C#)

(tested and works, just attach it to the platform)

using UnityEngine;
using System.Collections;

public class DragObject : MonoBehaviour
{
    private Plane plane;
    private bool dragging = false;
    private Vector3 offset;

    void Start ()
    {
        // the first vector is the normal vector pointing towards us.
        // that results in a xy-plane.
        // the point at the end specifies through which point the plane goes
        plane = new Plane(-Vector3.forward,new Vector3(0,0,0)); 
    }
    Vector3 GetMousePos()
    {
        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
        float distance;
        if (plane.Raycast(ray, out distance))
        {
            return ray.GetPoint(distance);
        }
        return Vector3.zero;
    }

    void OnMouseDown()
    {
        dragging = true;
        offset = transform.position - GetMousePos();
    }

    void Update ()
    {
        if (dragging && Input.GetMouseButton(0))
        {
            transform.position = GetMousePos() + offset;
        }
        else
        {
            dragging = false;
        }
    }
}


edit

Here’s the quickly converted JS version :wink: most stays the same:

private var plane : Plane;
private var dragging = false;
private var offset : Vector3;

function Start ()
{
    plane = new Plane(-Vector3.forward,new Vector3(0,0,0)); 
}

function GetMousePos() : Vector3
{
    var ray = Camera.main.ScreenPointToRay(Input.mousePosition);
    var distance : float;
    if (plane.Raycast(ray, distance))
    {
        return ray.GetPoint(distance);
    }
    return Vector3.zero;
}

function OnMouseDown()
{
    dragging = true;
    offset = transform.position - GetMousePos();
}

function Update ()
{
    if (dragging && Input.GetMouseButton(0))
    {
        transform.position = GetMousePos() + offset;
    }
    else
    {
        dragging = false;
    }
}

Here’s the easiest way. Very simply:

#Actually make a plane,

it will be your “touch plane”.

Put it anywhere you want.

(Make it big enough to cover the whole camera frustrum.)

Of course, just turn off the renderer so it is invisible.

Copy and paste Drag.cs below. Put Drag on the blue object.

Be sure to drag your “touch plane” to the Plane variable.

90277-c.png

You’re done. It all works.

// Drag.cs - 2017
using UnityEngine;
public class Drag : MonoBehaviour {
    public MeshCollider plane;	// drag your plane to here in the Editor
    private Vector3 holdOffset;
    private bool dragging = false;
	Vector3 PointOnPlane() {
		Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
		RaycastHit h;
		if (plane.Raycast(ray, out h, 30f)) { return h.point; }
		return Vector3.zero;
	}
	void OnMouseDown() {
		dragging = true;
		holdOffset = transform.position - PointOnPlane();
	}
	void OnMouseUp() { dragging = false; }
	void Update () { if (dragging) { transform.position = PointOnPlane() + holdOffset; } }
}

That’s it.