2016-05-27 3 views
9

В эти дни невероятно легко перетащить элементы пользовательского интерфейса в Unity: сделайте несколько элементов пользовательского интерфейса. Добавить компонент -> Событие ->Событие Trigger. Опустите скрипт ниже. Нажмите, чтобы добавить четыре очевидных триггера. Все готово.Пользовательский интерфейс Unity3D, вычисление позиции перетаскивания элемента?

Однако.

Я полностью потерял в отношениях между указатель координат и UI координаты (как показано в RectTransform и так далее).

В DragIt ниже: как, черт возьми, вы перемещаете панель пользовательского интерфейса правильно под пальцем?

Скажем, у вас есть одна большая панель с десятью UIButton, сидящими на панели с Dragster на кнопках. Какова взаимосвязь между зонами RectTransform и указателем мыши ...

Короче говоря, как вы перемещаете одну из кнопок вокруг в DragIt() ниже?

/* modern Unity drag of UI element */ 
using UnityEngine; 
using UnityEngine.UI; 
using UnityEngine.Events; 
using UnityEngine.EventSystems; 
public class Dragster:MonoBehaviour 
    { 
    public int index; // number each of your UI items 
    static bool beingDragged = false; 
    static int dragFrom; 
    public void DragStart() 
     { 
     beingDragged = true; dragFrom = index; 
     } 
    public void DragIt() 
     { 
     ? ? W T F ? ? 
     } 
    public void DragEnd() 
     { 
     beingDragged = false; 
     } 
    public void DroppedBra() 
     { 
     Debig.Log("Drag: from/to " +dragFrom +" --> " +index); 
     } 
    } 
+0

Для преобразования данных указателя в координаты пользовательского интерфейса вы можете изучить RectTransformUtilty. –

+0

Итак, напечатав все это, я снова это прочитал и понял, что вы привязали «Dragster» к каждому пользовательскому интерфейсу, который упростил код. Мое решение было совсем другим. Он использует один скрипт только для обнаружения любой панели/изображения и кнопки, а затем перетаскивает их. Вы не присоединяете его к каждому пользовательскому интерфейсу каждого пользовательского интерфейса. Он должен быть прикреплен к родительскому холсту. Это все отходы. Простите меня за то, что тратили свое время. Я буду читать вопрос в следующий раз .... – Programmer

+0

Его только полезно, если вы хотите использовать только один скрипт. Иначе это пустая трата времени. – Programmer

ответ

4

Для Draging вещи я просто сделать это:

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"); 

    } 
} 
+0

@JoeBlow wait, так что вы хотите перетащить элементы, отличные от UI, или элементы пользовательского интерфейса? –

+0

@JoeBlow Я создал совершенно пустую сцену. Не снимать. Просто холст, панель на холсте, кнопка на панели и объект EventSystem. Мой код очень сильно перетаскивает кнопку. Некоторые странные графические сбои из-за отсутствия камеры, но драпировка в порядке. –

+0

@ JoeBlow right Я отказался от этого и просто пошел с тем, что работает. –

8

Я хотел бы сделать свой сценарий реализовать перетаскивать интерфейсы

public class Dragster:MonoBehaviour,IBeginDragHandler, IEndDragHandler, IDragHandler

которые сделают вашу DragIt функция стала

public void OnDrag(PointerEventData eventData) 
{ 
    transform.position += (Vector3)eventData.delta; 
} 

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

Если бы еще лучше использовать компонент EventTrigger (менее Предпочтительнее путь), вам просто нужно изменить DragIt функцию DragIt(PointerEventData eventData) и использовать опцию Dynamic EvenData в выпадающем списке для триггера, чтобы получить PointerEventData доступа к дельте информация


Вот на самом деле общее, полное, решение для перетаскивания «UnityEngine.UI` элементов, на основе Ури & кода Колтона. Просто скопируйте и вставьте.

Поразительно копировать и вставлять никакой опасности совершенного перетаскивания для Unity UI, WTT Колтон & Uri:

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

public class UNCDraggable:MonoBehaviour, 
IBeginDragHandler, IDragHandler, IEndDragHandler, IDropHandler 
    { 
    public Image ghost; 
    // note DON'T try to drag the actual item: it's not worth the hassle. 
    // a problem arises where you can't have it on top (as you would want 
    // visually), and still easily get the drops. always use a ghost. 
    // even if you want the "original invisible" while dragging, 
    // simply hide it and use a ghost. everything is tremendously 
    // easier if you do not move the originals. 

    void Awake() 
     { 
     ghost.raycastTarget = false; 
     // (just in case you forgot to do that in the Editor) 
     ghost.enabled = false; 
     } 

    public void OnBeginDrag(PointerEventData eventData) 
     { 
     ghost.transform.position = transform.position; 
     ghost.enabled = true; 
     } 

    public void OnDrag(PointerEventData eventData) 
     { 
     ghost.transform.position += (Vector3)eventData.delta; 
     } 

    public void OnEndDrag(PointerEventData eventData) 
     { 
     ghost.enabled = false; 
     } 

    public void OnDrop(PointerEventData data) 
     { 
     GameObject fromItem = data.pointerDrag; 
     if (data.pointerDrag == null) return; // (will never happen) 

     UNCDraggable d = fromItem.GetComponent<UNCDraggable>(); 
     if (d == null) 
      { 
      // means something unrelated to our system was dragged from. 
      // for example, just an unrelated scrolling area, etc. 
      // simply completely ignore these. 
      return; 
      // note, if very unusually you have more than one "system" 
      // of UNCDraggable items on the same screen, be careful to 
      // distinguish them! Example solution, check parents are same. 
      } 

     Debug.Log ("dropped " + fromItem.name +" onto " +gameObject.name); 

     // your code would look probably like this: 
     YourThings fromThing = fromItem.GetComponent<YourButtons>().info; 
     YourThings untoThing = gameObject.GetComponent<YourButtons>().info; 

     yourBossyObject.dragHappenedFromTo(fromThing, untoThing); 
     } 
    } 
+1

Также @JoeBlow да, система событий единства привязана к системе пользовательского интерфейса. используя дельта, а не только настройку позиции преобразования, вы поддерживаете смещение туда, где пользователь на самом деле нажал, поэтому, если они нажмут один угол, а ваш стержень находится в другом углу, он перейдет к этой новой позиции. –

+0

@JoeBlow Пробовал ответ Ури, и он работает. Это сработало. Вам все еще нужен мой ответ? Я тоже решил некоторые проблемы lol – Programmer

+0

@ColtonWhite Ваш код не компилировался. transform.position + = eventData.delta; не работал. Я изменил его и удалил знак +, и пользовательский интерфейс даже не переместился в правильное положение. Он прыгнул в нижнюю часть экрана. Ответ Ури работал. Может быть, я делал это неправильно ... – Programmer

3

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

Моя официальная цель - предоставить способ сделать это, не используя bool beingDragged = false;. Вы просто не знаете, какой из Button или Image перетаскивается, если вы делаете это так.

Перетаскивание UI:

Преобразование Screenpoint в локальной точке RectTransform с помощью RectTransformUtility затем использовать Canvas.transform.TransformPoint, чтобы выяснить, где именно ребенок пользовательский интерфейс.

public Canvas parentCanvasOfImageToMove; 
Vector2 pos; 
RectTransformUtility.ScreenPointToLocalPointInRectangle(parentCanvasOfImageToMove.transform as RectTransform, eventData.position, parentCanvasOfImageToMove.worldCamera, out pos); 
UIToMove.transform.position = parentCanvasOfImageToMove.transform.TransformPoint(pos); 

Код перетаскивания выглядит более сложным, чем другой код перетаскивания в других ответах, но он, кажется, работает в каждом режиме камеры Canvas.

обнаруживая, который объект собирается быть втянута:

Самый простой способ сделать это, чтобы создать глобальную переменную, которую можно использовать для сохранения какой объект пользователь хочет перетащить в функции OnBeginDrag вы можете перетащить этот объект находится в OnDrag. Установите для этого объекта значение null, когда вызывается OnEndDrag.

objectToBeDragged = eventData.pointerCurrentRaycast.gameObject; 

Это необходимо сделать один раз в функции OnBeginDrag, а затем сохранить в глобальную переменную.

Вы не можете сделать следующее в OnDrag функции

if (eventData.pointerCurrentRaycast.gameObject == someOtherUI) 
{ 
    someOtherUI....drag 
} 

Даже если предположить, чтобы работать, это не иногда. Он даже возвращает null иногда во время OnDrag. Вот почему это нужно сделать в функции OnBeginDrag.

Обнаружение и перетаскивании кнопки Vs Image:

Обнаружение, если пользовательский интерфейс просто Image и перетаскиванием Image очень легко.

objectToBeDragged = eventData.pointerCurrentRaycast.gameObject; 
Button tempButton = objectToBeDragged.GetComponent<Button>(); 
Image tempImage = objectToBeDragged.GetComponent<Image>(); 

Если tempImage является неnull и tempButton является null то, что это изображение.

Детектирование если UI просто Button и перетаскивание Button является НЕ легко. Когда кнопка нажата на сторона/край, возвращается имя Button, что хорошо. Но в большинстве случаев щелчок на Button происходит в серединеButton, который делает не, возвращает экземпляр или имя кнопки, но вместо этого возвращает Text (дочерний объект). Вы НЕ МОЖЕТ переместить текст в виде кнопки. Это не сработает.

objectToBeDragged = eventData.pointerCurrentRaycast.gameObject; 
Button tempButton = objectToBeDragged.GetComponent<Button>(); 
Image tempImage = objectToBeDragged.GetComponent<Image>(); 
Text tempText = objectToBeDragged.GetComponent<Text>(); 

если tempText является не нуля, получить GetComponentInParent изображений и кнопку компоненты текста. Если Image не является нулевым, а Button не является нулевым, то это Button.

if (tempText != null) 
{ 
    tempButton = tempText.GetComponentInParent<Button>(); 
    tempImage = tempText.GetComponentInParent<Image>(); 
    if (tempButton != null && tempImage != null) 
    { 
     //This is a Button 
    } 
} 

Ниже приведен полный сценарий перетаскивания изображения/панели и кнопки пользовательского интерфейса. Любая кнопка, которую нужно перетащить, следует поместить в массив UIButtons, и любая панель/изображение, которое нужно перетащить, следует поместить в массив UIPanels. Он будет игнорировать другой пользовательский интерфейс, который не находится в массиве.

public class UIDRAGGER : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler 
{ 
    public Canvas parentCanvasOfImageToMove; 

    //10 UI Buttons (Assign in Editor) 
    public Button[] UIButtons; 

    //2 UI Panels/Images (Assign in Editor) 
    public Image[] UIPanels; 

    //Hold which Button or Image is selected 
    private Button selectedButton; 
    private Image selectedUIPanels; 

    //Used to make sure that the UI is position exactly where mouse was clicked intead of the default center of the UI 
    Vector3 moveOffset; 

    //Used to decide which mode we are in. Button Drag or Image/Panel Mode 
    private DragType dragType = DragType.NONE; 


    void Start() 
    { 
     parentCanvasOfImageToMove = gameObject.GetComponent<Canvas>(); 
    } 

    //Checks if the Button passed in is in the array 
    bool buttonIsAvailableInArray(Button button) 
    { 
     bool _isAValidButton = false; 
     for (int i = 0; i < UIButtons.Length; i++) 
     { 
      if (UIButtons[i] == button) 
      { 
       _isAValidButton = true; 
       break; 
      } 
     } 
     return _isAValidButton; 
    } 

    //Checks if the Panel/Image passed in is in the array 
    bool imageIsAvailableInArray(Image image) 
    { 
     bool _isAValidImage = false; 
     for (int i = 0; i < UIPanels.Length; i++) 
     { 
      if (UIPanels[i] == image) 
      { 
       _isAValidImage = true; 
       break; 
      } 
     } 
     return _isAValidImage; 
    } 

    void selectButton(Button button, Vector3 currentPos) 
    { 
     //check if it is in the image array that is allowed to be moved 
     if (buttonIsAvailableInArray(button)) 
     { 
      //Make the image the current selected image 
      selectedButton = button; 
      dragType = DragType.BUTTONS; 
      moveOffset = selectedButton.transform.position - currentPos; 
     } 
     else 
     { 
      //Clear the selected Button 
      selectedButton = null; 
      dragType = DragType.NONE; 
     } 
    } 

    void selectImage(Image image, Vector3 currentPos) 
    { 
     //check if it is in the image array that is allowed to be moved 
     if (imageIsAvailableInArray(image)) 
     { 
      //Make the image the current selected image 
      selectedUIPanels = image; 
      dragType = DragType.IMAGES; 
      moveOffset = selectedUIPanels.transform.position - currentPos; 
     } 
     else 
     { 
      //Clear the selected Button 
      selectedUIPanels = null; 
      dragType = DragType.NONE; 
     } 
    } 


    public void OnBeginDrag(PointerEventData eventData) 
    { 
     GameObject tempObj = eventData.pointerCurrentRaycast.gameObject; 

     if (tempObj == null) 
     { 
      return; 
     } 

     Button tempButton = tempObj.GetComponent<Button>(); 
     Image tempImage = tempObj.GetComponent<Image>(); 
     Text tempText = tempObj.GetComponent<Text>(); 

     //For Offeset Position 
     Vector2 pos; 
     RectTransformUtility.ScreenPointToLocalPointInRectangle(parentCanvasOfImageToMove.transform as RectTransform, eventData.position, parentCanvasOfImageToMove.worldCamera, out pos); 


     //Button must contain Text then Image and Button as parant 
     //Check if this is an image 
     if (tempButton == null || tempImage == null) 
     { 
      //Button not detected. Check if Button's text was detected 
      if (tempText != null) 
      { 
       //Text detected. Now Look for Button and Image in the text's parent Object 
       tempButton = tempText.GetComponentInParent<Button>(); 
       tempImage = tempText.GetComponentInParent<Image>(); 

       //Since child is text, check if parents are Button and Image 
       if (tempButton != null && tempImage != null) 
       { 
        //This is a Button 
        selectButton(tempButton, parentCanvasOfImageToMove.transform.TransformPoint(pos)); 
       } 
       //Check if there is just an image 
       else if (tempImage != null) 
       { 
        //This is an Image 
        selectImage(tempImage, parentCanvasOfImageToMove.transform.TransformPoint(pos)); 
       } 
      } 
      else 
      { 
       //This is an Image 
       selectImage(tempImage, parentCanvasOfImageToMove.transform.TransformPoint(pos)); 
      } 
     } 
     //Check if there is just an image 
     else if (tempImage != null) 
     { 
      selectImage(tempImage, parentCanvasOfImageToMove.transform.TransformPoint(pos)); 
     } 
    } 

    public void OnDrag(PointerEventData eventData) 
    { 
     Vector2 pos; 
     if (dragType == DragType.BUTTONS) 
     { 
      RectTransformUtility.ScreenPointToLocalPointInRectangle(parentCanvasOfImageToMove.transform as RectTransform, eventData.position, parentCanvasOfImageToMove.worldCamera, out pos); 
      selectedButton.transform.position = parentCanvasOfImageToMove.transform.TransformPoint(pos) + moveOffset; 
     } 
     else if (dragType == DragType.IMAGES) 
     { 
      RectTransformUtility.ScreenPointToLocalPointInRectangle(parentCanvasOfImageToMove.transform as RectTransform, eventData.position, parentCanvasOfImageToMove.worldCamera, out pos); 
      selectedUIPanels.transform.position = parentCanvasOfImageToMove.transform.TransformPoint(pos) + moveOffset; 
     } 
    } 


    public void OnEndDrag(PointerEventData eventData) 
    { 
     //Buttons 
     if (dragType == DragType.BUTTONS || dragType == DragType.IMAGES) 
     { 
      selectedButton = null; 
      selectedUIPanels = null; 
      dragType = DragType.NONE; 
     } 
    } 

    DragType getCurrentDragType() 
    { 
     return dragType; 
    } 

    private enum DragType { NONE, BUTTONS, IMAGES }; 
} 
+0

whoa, это BOATLOAD ИНФОРМАЦИОННЫХ СПАСИБО !!!!!!!! – Fattie

Смежные вопросы