Прежде всего, Все остальные участники этой статьи работают очень хорошо. Я работал над этим так долго и просто хотел опубликовать его здесь. Это добавляет способ предотвратить перемещение других нежелательных объектов пользовательского интерфейса.
Моя официальная цель - предоставить способ сделать это, не используя 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 };
}
Для преобразования данных указателя в координаты пользовательского интерфейса вы можете изучить RectTransformUtilty. –
Итак, напечатав все это, я снова это прочитал и понял, что вы привязали «Dragster» к каждому пользовательскому интерфейсу, который упростил код. Мое решение было совсем другим. Он использует один скрипт только для обнаружения любой панели/изображения и кнопки, а затем перетаскивает их. Вы не присоединяете его к каждому пользовательскому интерфейсу каждого пользовательского интерфейса. Он должен быть прикреплен к родительскому холсту. Это все отходы. Простите меня за то, что тратили свое время. Я буду читать вопрос в следующий раз .... – Programmer
Его только полезно, если вы хотите использовать только один скрипт. Иначе это пустая трата времени. – Programmer