Прежде всего, все остальные ответы в этом посте работают очень хорошо. Я так долго работал над этим и просто хотел опубликовать это здесь. Он добавляет способ предотвратить перетаскивание других нежелательных объектов пользовательского интерфейса.
Моей официальной целью было предоставить способ сделать это без использования bool beingDragged = false;
. Вы просто не будете знать, какой Button
или Image
перетаскивается, если вы сделаете это так.
Перетаскивание пользовательского интерфейса:
Преобразуйте точку экрана в локальную точку в 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
.
Обнаружение и перетаскивание кнопки по сравнению с изображением:
Определить, является ли пользовательский интерфейс просто Image
и перетаскиванием Image
, очень просто.
objectToBeDragged = eventData.pointerCurrentRaycast.gameObject;
Button tempButton = objectToBeDragged.GetComponent<Button>();
Image tempImage = objectToBeDragged.GetComponent<Image>();
Если tempImage
не null
, а tempButton
равно null
, то это Изображение.
Определить, является ли пользовательский интерфейс просто 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
не равно null, получите 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 };
}
person
Programmer
schedule
27.05.2016
Dragster
к каждому пользовательскому интерфейсу, что упростило кодирование. Мое решение было совершенно другим. Он использует только один скрипт для обнаружения любой панели/изображения и кнопки, а затем перетаскивает их. Вы не прикрепляете его к каждому пользовательскому интерфейсу каждого пользовательского интерфейса. Он должен быть прикреплен к родительскому холсту. Это все отходы. Простите меня за потраченное вами время. Я прочитаю вопрос прямо в следующий раз.... - person Programmer   schedule 27.05.2016