- Home /
Radial distance between two points
Hi! I'm having a problem. I need to drag an object on the screen (x and y position). I'm dragging it with touch, but that's not the issue. The object needs to be dragged from the position of the touch, not it's center, also, the object's movement might be restricted by a radius and/or limited to move along an axis (x or y) and finally, if the finger leaves the circle defined by the radius, the object must keep following its relative position without getting out the radius.
To do this I'm using the code pasted below. It works like this: It creates an empty object in the position of the touch (dragMarker) and then it sets this dragMarker as the parent of the object to drag. Then, I update the postion of the dragMarker to track the touch. This works fine, but when I apply the radial restrictions things go wrong.
I believe that if I change the restriction radius (maxMovementRadius) to take into account the radial distance between the objects position (transform.position) and the dragMarker's position I can fix this, but I'm not sure how to do this (image). There may be a better approach to all this tough...
I'm using easy touch and there are some other functianlities in the code. You don't need to pay attention to the update function. Also, SetX and SetY are just custom extensions to transform that basically do what they say. (I have pasted those methods at the end of the code, but they would not work like that).
Thanks and sorry for the length of the question.
using UnityEngine;
using System.Collections;
/// <summary>
/// Put this script on the object you want to be able to drag.
/// It must be on the Touchable,the Floor or the Enemy layer.
/// EasyTouch must be in the project.
/// </summary>
[AddComponentMenu("Utilities/Dragable Object")]
public class DragableObject : MonoBehaviour
{
/// <summary>
/// Allowed movement radius. If 0, the movement is free.
/// </summary>
public float maxMovementRadius;
public bool lockXPosition;
public bool lockYPosition;
public float movementDamp = 10f;
public bool useAndDestroy = false;
public int maxPosibleUses = 1;
[Range(0f,1f)]
public float alpha = 1;
private GameObject dragMarker;
private Vector3 origPosition = Vector3.zero;
private Vector3 origPositionMark = Vector3.zero;
private bool used = false;
private int usesCount = 0;
private Color newColor = new Color();
private ParticleSystem pufParticles;
private LineRenderer lineRenderer;
void OnEnable()
{
EasyTouch.On_Drag += On_Drag;
EasyTouch.On_DragStart += On_DragStart;
EasyTouch.On_DragEnd += On_DragEnd;
}
void OnDisable()
{
UnsubscribeEvent();
}
void OnDestroy()
{
UnsubscribeEvent();
}
void UnsubscribeEvent()
{
EasyTouch.On_Drag -= On_Drag;
EasyTouch.On_DragStart -= On_DragStart;
EasyTouch.On_DragEnd -= On_DragEnd;
}
void Awake()
{
//save the original position of the object
origPosition = transform.position;
Debug.Log("Original position: " + origPosition);
newColor = renderer.material.color;
pufParticles = transform.Find("PufParticles").GetComponent<ParticleSystem>();
}
void Update()
{
newColor.a = alpha;
renderer.material.color = newColor;
if (useAndDestroy)
{
if (PlayerController.ONOBJECT == gameObject)
{
used = true;
}
// if this conditions are meet it measn that the player has been over this object,
//but it is not here anymore. So if it is used object, it will increment the uses count until
// it reachs tha max number of uses and it destroy itself
if (PlayerController.ONOBJECT!= gameObject && used)
{
used = false;
usesCount++;
if(usesCount >= maxPosibleUses)
{
SelfDestruct();
}
}
}
}
// At the drag beginning
void On_DragStart(Gesture gesture)
{
// Verification that the action on the object
if (gesture.pickObject == gameObject)
{
//play sound
//play visual queue
dragMarker = new GameObject("Drag Marker");
dragMarker.transform.position = gesture.GetTouchToWordlPoint(transform.position.z, worldZ: true);
dragMarker.transform.rotation = Quaternion.identity;
gameObject.transform.parent = dragMarker.transform;
origPositionMark = dragMarker.transform.position;
Debug.Log("Drag Start. Marker Orig Position: " + origPositionMark);
}
}
// During the drag
void On_Drag(Gesture gesture)
{
if (gesture.pickObject == gameObject)
{
if (PlayerController.ONOBJECT != gameObject)
{
Vector3 position = gesture.GetTouchToWordlPoint(transform.position.z, worldZ: true);
Vector3 targetPos = Vector3.zero;
targetPos.x = lockXPosition ? origPositionMark.x : position.x;
targetPos.y = lockYPosition ? origPositionMark.y : position.y;
if (maxMovementRadius != 0)
{
//this radious should be the magnited of the vector that starts in origPosition and ends in the marker???
if (Vector3.Distance(origPosition, position) < maxMovementRadius)
{
dragMarker.transform.SetX(Mathf.Lerp(dragMarker.transform.position.x, targetPos.x, Time.deltaTime * movementDamp));
dragMarker.transform.SetY(Mathf.Lerp(dragMarker.transform.position.y, targetPos.y, Time.deltaTime * movementDamp));
Debug.Log("In radious");
}
else
{
Debug.Log("out of radious");
Vector3 newPos = position - origPosition;
newPos.Normalize();
newPos *= maxMovementRadius;
newPos += origPosition;
newPos.x = lockXPosition ? origPositionMark.x : newPos.x;
newPos.y = lockYPosition ? origPositionMark.y : newPos.y;
dragMarker.transform.position = newPos;
;
}
}
else
{
dragMarker.transform.SetX(Mathf.Lerp(dragMarker.transform.position.x, targetPos.x, Time.deltaTime * movementDamp));
dragMarker.transform.SetY(Mathf.Lerp(dragMarker.transform.position.y, targetPos.y, Time.deltaTime * movementDamp));
}
}
}
}
// At the drag end
void On_DragEnd(Gesture gesture)
{
//play sound
//play visual queue
transform.parent = null;
Destroy(dragMarker);
}
void SelfDestruct()
{
pufParticles.Play();
alpha = 0;
collider2D.enabled = false;
}
}
//extensiond
public static class TransformExtensions
{
public static void SetX(this Transform t, float n)
{
t.position = new Vector3(n, t.position.y, t.position.z);
}
public static void SetY(this Transform t, float n)
{
t.position = new Vector3(t.position.x, n, t.position.z);
}
public static void SetZ(this Transform t, float n)
{
t.position = new Vector3(t.position.x, t.position.y, n);
}
}
Answer by josessito · May 04, 2014 at 09:07 PM
Ok, this is embarrasing. I was doing things much more complicated than they needed to be. Here is the code. The approach is much simpler and logical. using UnityEngine; using System.Collections;
/// <summary>
/// Put this script on the object you want to be able to drag.
/// It must be on the Touchable,the Floor or the Enemy layer.
/// EasyTouch must be in the project.
/// </summary>
[AddComponentMenu("Utilities/Dragable Object")]
public class DragableObject : MonoBehaviour
{
/// <summary>
/// Allowed movement radius. If 0, the movement is free.
/// </summary>
public float maxMovementRadius;
public bool lockXPosition;
public bool lockYPosition;
public float movementDamp = 10f;
private Vector3 deltaPosition;
private Vector3 origPosition = Vector3.zero;
void OnEnable()
{
EasyTouch.On_Drag += On_Drag;
EasyTouch.On_DragStart += On_DragStart;
EasyTouch.On_DragEnd += On_DragEnd;
}
void OnDisable()
{
UnsubscribeEvent();
}
void OnDestroy()
{
UnsubscribeEvent();
}
void UnsubscribeEvent()
{
EasyTouch.On_Drag -= On_Drag;
EasyTouch.On_DragStart -= On_DragStart;
EasyTouch.On_DragEnd -= On_DragEnd;
}
void Awake()
{
//save the original position of the object
origPosition = transform.position;
Debug.Log("Original position: " + origPosition);
}
void Update()
{
}
// At the drag beginning
void On_DragStart(Gesture gesture)
{
// Verification that the action on the object
if (gesture.pickObject == gameObject)
{
Vector3 position = gesture.GetTouchToWordlPoint(transform.position.z, worldZ: true);
//here it is stored the delta betwwen thr touch and the objecs center position
deltaPosition = position - transform.position;
}
}
// During the drag
void On_Drag(Gesture gesture)
{
if (gesture.pickObject == gameObject)
{
if (PlayerController.ONOBJECT != gameObject)
{
Vector3 position = gesture.GetTouchToWordlPoint(transform.position.z, worldZ: true);
Vector3 targetPos = Vector3.zero;
targetPos.x = lockXPosition ? origPosition.x : position.x - deltaPosition.x;
targetPos.y = lockYPosition ? origPosition.y : position.y - deltaPosition.y;
if (maxMovementRadius != 0)
{
if (Vector3.Distance(origPosition, (position-deltaPosition)) < maxMovementRadius)
{
transform.position = Vector3.Lerp(transform.position, targetPos, Time.deltaTime * movementDamp);
}
else
{
Vector3 newPos = position - deltaPosition - origPosition;
newPos.Normalize();
newPos *= maxMovementRadius;
newPos += origPosition;
newPos.x = lockXPosition ? origPosition.x : newPos.x;
newPos.y = lockYPosition ? origPosition.y : newPos.y;
transform.position = Vector3.Lerp(transform.position, newPos, Time.deltaTime * movementDamp);
}
}
else
{
transform.position = Vector3.Lerp(transform.position, targetPos, Time.deltaTime * movementDamp);
}
}
}
}
// At the drag end
void On_DragEnd(Gesture gesture)
{
//play sound
//play visual queue
}
}