2017-01-13 3 views
0

Я новичок в концепции преобразования координат экрана в мировые координаты в 3D-мире вообще, тем более в Unity. Я использую библиотеку UnityEngine.EventSystems, реализуя IDragHandler, так как я хочу, чтобы это работало одинаково независимо от того, является ли источник мыши или сенсорным.Unity3D OnDrag move 3D-объект не соответствует указателю

Я хочу перетащить трехмерный объект в мировом пространстве, заблокированный до одной позиции z. Я нашел этот отличный кусок кода, который я сейчас с помощью: http://coffeebreakcodes.com/drag-object-with-mouse-unity3d/

тот же код можно найти в ответе здесь: Drag 3d object using fingers in unity3d

Он работает именно так, как я хочу, чтобы он, кроме одной вещи : Преобразование работает нормально, когда начинается перетаскивание, но объект делает больше движений, чем указатель, тем хуже, чем дальше от исходного положения объекта, которое он получает, как если бы движение умножалось на нечто большее, чем дальше от оригинала я получаю.

Это мой код, который в основном такой же, как и в приведенной выше ссылке, кроме использования указателя на PointerEventData координирует вместо Input.mousePosition (изменение, которые не влияют на поведение):

public class DragInput : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler 
{ 
    private Vector3 screenPoint; 
    private Vector3 offset; 

    public void OnBeginDrag(PointerEventData eventData) 
    { 
     screenPoint = Camera.main.WorldToScreenPoint(transform.position); 
     offset = transform.position - Camera.main.ScreenToWorldPoint(new Vector3(eventData.position.x, eventData.position.y, screenPoint.z)); 
    } 

    public void OnDrag(PointerEventData eventData) 
    { 
     Vector3 cursorPoint = new Vector3(eventData.position.x, eventData.position.y, screenPoint.z); 
     Vector3 cursorPosition = Camera.main.ScreenToWorldPoint(cursorPoint) + offset; 
     transform.position = cursorPosition; 
    } 

    public void OnEndDrag(PointerEventData eventData) 
    { 
    } 
} 

EDIT: Это видео клип демонстрирует поведение я описывающее: https://www.dropbox.com/s/qfx2p6kznizft1q/Unity%202017-01-13%2014-32-15-89.avi?dl=0

+0

Что такое режим проекции камеры? – Programmer

+0

Объект игры с основной камерой (у меня есть только одна камера). В компоненте камеры установлен Projection to Perspective. – Helena

ответ

0

Причина проблемы, которую я опубликовал, была связана с тем, что я забыл физический рикер в MainCamera. У меня был GraphicsRaycaster на холсте, но не присутствовал ни один физический рикастер - я думаю, что это могло вызвать странное поведение.

Однако мой код, поскольку он имеет проблемы с другим желаемым поведением, описанным мной, перемещает объект на фиксированное расстояние до камеры. См. Ответ @ Programmer, чтобы узнать, как это исправить.

Их код, однако, не тот, который решил проблему, которая была целью этого поста, поэтому их ответ не был принятым ответом.

-1

Взгляните на этот фрагмент:

pos = Camera.main.ScreenToWorldPoint (Vector3 (Input.GetTouch(0).position.x,Input.GetTouch(0).position.y, 5)); 
transform.position = new Vector3(pos.x, pos.y, pos.z); 

или еще у ожно попробовать этот класс, если это не работает, я из вариантов :)

using UnityEngine; 
using System.Collections; 

public class DragObject : MonoBehaviour { 

private float dist; 
private Vector3 v3Offset; 
private Plane plane; 
private bool ObjectMouseDown = false; 
public GameObject linkedObject; 

void OnMouseDown() { 
    plane.SetNormalAndPosition(Camera.main.transform.forward, transform.position); 
    Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition); 
    float dist; 
    plane.Raycast (ray, out dist); 
    v3Offset = transform.position - ray.GetPoint (dist);  
    ObjectMouseDown = true; 
} 

void OnMouseDrag() { 
    if (ObjectMouseDown == true){ 
     Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition); 
     float dist; 
     plane.Raycast (ray, out dist); 
     Vector3 v3Pos = ray.GetPoint (dist); 
     v3Pos.z = gameObject.transform.position.z; 
     v3Offset.z = 0; 
     transform.position = v3Pos + v3Offset; 

     if (linkedObject != null){ 
      linkedObject.transform.position = v3Pos + v3Offset; 
     } 
    } 
} 

void OnMouseOut() { 
    ObjectMouseDown = false; 
} 

} 
+0

Спасибо! Однако этот код определенно проще, чем мой, но он по-прежнему производит такое же поведение. – Helena

1

Это проблема перспективы при перемещении вокруг 3D объекта.

Вам нужно сделать Plane, скрыв положение мыши (пиксели экрана), чтобы проверить луч, а затем проверить, где они пересекаются.

using UnityEngine; 
using UnityEngine.EventSystems; 

public class DragInput : MonoBehaviour, IPointerDownHandler, IDragHandler, IEndDragHandler 
{ 
    Camera mainCamera; 
    float zAxis = 0; 
    Vector3 clickOffset = Vector3.zero; 

    // Use this for initialization 
    void Start() 
    { 
     mainCamera = Camera.main; 
     zAxis = transform.position.z; 
    } 

    public void OnPointerDown(PointerEventData eventData) 
    { 
     clickOffset = transform.position - mainCamera.ScreenPointToWoldOnPlane(eventData.position, zAxis); 
    } 

    public void OnDrag(PointerEventData eventData) 
    { 
     transform.position = mainCamera.ScreenPointToWoldOnPlane(eventData.position, zAxis) + clickOffset; 
    } 

    public void OnEndDrag(PointerEventData eventData) 
    { 

    } 
} 

public static class extensionMethod 
{ 
    public static Vector3 ScreenPointToWoldOnPlane(this Camera cam, Vector3 screenPosition, float zPos) 
    { 
     float enterDist; 
     Plane plane = new Plane(Vector3.forward, new Vector3(0, 0, zPos)); 
     Ray rayCast = cam.ScreenPointToRay(screenPosition); 
     plane.Raycast(rayCast, out enterDist); 
     return rayCast.GetPoint(enterDist); 
    } 
} 
+0

Спасибо! Это, однако, вызывает то же поведение, что и мой код. Может, я сделал что-то не так с другим компонентом, например, с моим холстом? – Helena

+0

Я сделал тест перед публикацией этого, и он работает. Это устранило проблему ... Вы скопировали код так, как есть? Если нет, сделайте это. Убедитесь, что модель не находится под любым GameObject. Это должно решить эту проблему! – Programmer

+0

Что вы имеете в виду, что «модель не под любым GameObject», какова модель, о которой вы говорите? – Helena