Unity3D Ui, Calculation for Position Dragging an Item

Unity3D UI, calculation for position dragging an item?

For Draging stuff I just do this :

using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;

public class Draggable : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler {



public void OnBeginDrag(PointerEventData eventData) {

}

public void OnDrag(PointerEventData eventData) {
//Debug.Log ("OnDrag");

this.transform.position = eventData.position;

}

public void OnEndDrag(PointerEventData eventData) {
Debug.Log ("OnEndDrag");

}
}

Here's the identical amazing URIPOPOV CODE with two simple features which you always need when dragging:

// allow dragging with two basic problem fixes:
// - limit drag to the parent box
// - don't "jump" based on where you hold down

100% tested:

Note that you MUST USE the scale conversion code from #programmer below.

using UnityEngine;
using UnityEngine.EventSystems;

public class AmazingUPDrag : MonoBehaviour,
IBeginDragHandler, IDragHandler, IEndDragHandler
{

RectTransform rt;
Vector2 dragOffset = Vector2.zero;
Vector2 limits = Vector2.zero;

Canvas canvas;

void Awake()
{
rt = GetComponent<RectTransform>();
canvas = GetComponentInParent<Canvas>();
}

public void OnBeginDrag(PointerEventData eventData)
{
dragOffset = ActualPos(eventData.position) - (Vector2)transform.position;
limits = transform.parent.GetComponent<RectTransform>().rect.max;

limits.x = limits.x - 100f;
limits.y = limits.y - 100f;
}

public void OnDrag(PointerEventData eventData)
{
transform.position = ActualPos(eventData.position) - dragOffset;

var p = transform.localPosition;
if (p.x < -limits.x) { p.x = -limits.x; }
if (p.x > limits.x) { p.x = limits.x; }
if (p.y < -limits.y) { p.y = -limits.y; }
if (p.y > limits.y) { p.y = limits.y; }
transform.localPosition = p;
}

public void OnEndDrag(PointerEventData eventData)
{
dragOffset = Vector2.zero;
}

Vector2 ActualPos(Vector2 unityDelusionPos)
{
Vector2 p;
RectTransformUtility.ScreenPointToLocalPointInRectangle(
(RectTransform)(canvas.transform),
unityDelusionPos,
canvas.worldCamera,
out p);
return canvas.transform.TransformPoint(p);
}

}

Unity drag and drop in world positions

So after a bit of playing around and inspecting the various values I was receiving from the calls to ScreenToWorldPoint I finally tracked down the issue.
In the code for my second attempted approach I found that I was using an incorrect value for the Z argument in ScreenToWorldPoint. After doing a bit of research I found that his should be the Z distance between the camera and the (i guess) touch surface.

Vector3 screenCenter = new Vector3(Screen.width * 0.5f, Screen.height * 0.5f, -Camera.main.transform.position.z);
Vector3 screenTouch = screenCenter + new Vector3(eventData.delta.x, eventData.delta.y, 0);

Thanks to everyone who took the time to read through my question.

Dragging Item With Icon Following Pointer Unity C#

Very fortunately, there is now an

incredibly simple way

to do this in Unity.

Here it is: https://stackoverflow.com/a/37473953/294884

Ask if you have more trouble!

How to make Unity UI object draggable when the objects are instantiating at runtime?

At the time you Instantiate your GameObject obj, do:

obj.addComponent("YourScript");

where YourScript is your script, which you have written, that attached to a GameObjects makes it draggable..

Alternatively, you instantiate a prefab, attach the script to the prefab through the editor.

This is preferrable because addComponent() will get deprecated in the next versions.

I also recommend to keep a List<YourInstantiatedObjectType> in the parent.

Unity drag doesn't work, object moves away from the pointer

It's better to use Screen Space - Overlay if the camera's viewport is unchanged. Then following code will work:

this.transform.position = eventData.position;

To use Screen Space - Camera, you need transform the event position into the camera space:

Vector3 position = eventData.position;
var canvas = image.canvas;
position.z = canvas.planeDistance;
image.transform.position = canvas.worldCamera.ScreenToWorldPoint(position);

drag and drop in unity, drag behind other UI elements

Try adding a "Canvas" component to your prefab and check "override sorting" and set sort order. I think I also had to add a graphic raycaster.

Inspector:

inspector

Unity - How to calculate new position for an object from pitch of another object in 3D

Hotspots

If you'd like to place something at a particular location on a generic object which can be scaled or transformed anywhere, then a "hotspot" can be particularly useful.

What's a hotspot?

Edit the target gameobject (the line in this case) and add an empty gameobject to it. Give it some appropriate name - "cross arms hotspot" for example, and then move it to the location where you'd like your other gameobject to target. Essentially, a hotspot is just an empty gameobject - a placement marker of sorts.

How do I use it?

All you need is a reference to the hotspot gameobject. You could do this by adding a little script to the pole gameobject which tracks it for you:

public class PowerPole : MonoBehaviour {
public GameObject CrossArmsHotspot; // Set this in the inspector
}

Then you can get that hotspot reference from any power pole instance like this:

var targetHotspot = aPowerPoleGameObject.GetComponent<PowerPole>().CrossArmsHotspot;

Then it's just a case of getting your target object to place itself where that hotspot is, using whichever technique you prefer. If you want it to just "stick" there, then:

void Start(){
targetHotspot = aPowerPoleGameObject.GetComponent<PowerPole>().CrossArmsHotspot;
}

void Update(){
transform.position = targetHotspot.transform.position;
}

would be a (simplfied) example.

A more advanced example using lerp to move towards the hotspot:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CrossArmsMover : MonoBehaviour
{
public GameObject PowerPole;
private GameObject targetHotspot;
public GameObject CrossArms;
public float TimeToTake = 5f;
private float timeSoFar;
private Vector3 startPosition;
private Quaternion startRotation;

// Start is called before the first frame update
void Start()
{
startPosition = CrossArms.transform.position;
startRotation = CrossArms.transform.rotation;
targetHotspot = PowerPole.GetComponent<PowerPole>().CrossArmsHotspot;
}

// Update is called once per frame
void Update()
{
timeSoFar+=Time.deltaTime;

var progress = timeSoFar/TimeToTake;

// Clamp it so it doesn't go above 1.
if(progress > 1f){
progress = 1f;
}

// Target position / rotation is..
var targetPosition = targetHotspot.transform.position;
var targetRotation = targetHotspot.transform.rotation;

// Lerp towards that target transform:
CrossArms.transform.position = Vector3.Lerp(startPosition, targetPosition, progress);
CrossArms.transform.rotation = Quaternion.Lerp(startRotation, targetRotation, progress);

}
}

Using Lerp whilst moving the target object around



Related Topics



Leave a reply



Submit