- Home /
Drag a sprite around with mouse, but have it not overlap other sprites
Basically, the user can drag sprites around in the scene, yet they cannot overlap. I sort of managed to achieve this using colliders, however, I experience collider tunneling. It's a real headache - how to have the sprites (irregular shape, no primitives available) move around, but not overlap other sprites.
Edit: Alright, asking questions after 18+ hours of frustrating work is not a good idea! To elaborate more on the question - all of the sprites have got convex mesh colliders. I'm using rigidbody.movePosition to drag the sprite. This works really well if I move the mouse slowly, but whenever I start moving fast - the sprite, with its' collider, starts jumping right through other sprites and so forth. My first idea was to move the sprite with forces, setting a maximum speed, but this didn't quite work with my drag, because it would neither move fast enough, nor position properly when I let go.
Also, while this may seem strange - I'm working in 3D space, rather than 2D, because of the nature of the game and my own camera script, which is my pride and joy, but only works with a perspective camera.
In addition, I'm adding the main script I use for moving around.
using UnityEngine;
using System.Collections;
[RequireComponent(typeof(Rigidbody))]
public class Dragable : MonoBehaviour
{
public int normalCollisionCount = 0;
public float collisionMoveFactor = .01f;
public bool freezeRotationOnDrag = true;
public Camera cam ;
private Rigidbody myRigidbody ;
private Transform myTransform ;
private bool canMove = false;
private bool gravitySetting ;
private bool freezeRotationSetting ;
private int collisionCount = 0;
private Transform camTransform;
void Start ()
{
myRigidbody = rigidbody;
myTransform = transform;
cam = Camera.main;
}
void OnMouseDown ()
{
canMove = true;
gravitySetting = myRigidbody.useGravity;
freezeRotationSetting = myRigidbody.freezeRotation;
myRigidbody.useGravity = false;
myRigidbody.freezeRotation = freezeRotationOnDrag;
}
void OnMouseUp ()
{
canMove = false;
myRigidbody.useGravity = gravitySetting;
myRigidbody.freezeRotation = freezeRotationSetting;
if (!myRigidbody.useGravity)
{
Vector3 pos = myTransform.position;
myTransform.position = pos;
}
}
void OnCollisionEnter ()
{
collisionCount++;
}
void OnCollisionExit ()
{
collisionCount--;
}
void FixedUpdate ()
{
if (!canMove)
{
return;
}
myRigidbody.velocity = Vector3.zero;
myRigidbody.angularVelocity = Vector3.zero;
Vector3 pos = myTransform.position;
myTransform.position = pos;
Vector3 mousePos = Input.mousePosition;
Vector3 move = cam.ScreenToWorldPoint(new Vector3(mousePos.x, mousePos.y, 9.35f)) - myTransform.position;
if (collisionCount > normalCollisionCount)
{
move = move.normalized*collisionMoveFactor;
}
myRigidbody.MovePosition(myRigidbody.position + move);
}
}
You're on the right track. I would use a rigidbody driver. Ins$$anonymous$$d of simply setting the position of your dragged sprite, set the position of something else that it can follow. I would connect my sprite to a distance joint then just move the distance joint around. That way physics will still move your sprite & react to collisions.
I'll try it out, although it's a real mental breakdown for me. I should also elaborate more on the question itself :) And please, elaborate more as well ^w^
Your answer