Fat*_*tie 12 c# unity-game-engine unity3d-ui
现在,在Unity中拖动UI元素非常容易:制作一些UI项目.添加组件 - >事件 - > 事件触发器.放在下面的脚本上.单击以添加四个明显的触发器.你完成了.
然而.
我完全迷失了指针坐标和UI坐标之间的关系(如RectTransform中所见,等等).
在DragIt
下面:你怎么在手指下正确移动UI面板?
假设你有一个大面板,十个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);
}
}
Run Code Online (Sandbox Code Playgroud)
Col*_*ite 10
我会让你的脚本实现拖动界面
public class Dragster:MonoBehaviour,IBeginDragHandler, IEndDragHandler, IDragHandler
这将使你的DragIt
功能成为
public void OnDrag(PointerEventData eventData)
{
transform.position += (Vector3)eventData.delta;
}
Run Code Online (Sandbox Code Playgroud)
允许您访问该事件的增量(鼠标移动了多少)以便能够移动您的对象.
如果您仍然宁愿使用EventTrigger组件(不太喜欢的方式),您只需要将DragIt
函数更改为DragIt(PointerEventData eventData)
并在下拉列表中使用Dynamic EvenData选项,以便触发器接收PointerEventData以访问增量信息
这里实际上是基于Uri&Colton代码拖放'UnityEngine.UI`项目的完整解决方案.只需复制并粘贴即可.
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);
}
}
Run Code Online (Sandbox Code Playgroud)
首先,这篇文章中的所有其他的工作都非常好.我在这方面工作了很长时间,只想在这里发布.它添加了一种方法来防止拖动其他不需要的UI对象.
我的官方目标是在不使用的情况下提供一种方法bool beingDragged = false;
.你只是不知道Button
或者Image
,如果你不喜欢它正在拖动.
拖动UI:
借助于将Rectpoint转换为RectTransform中的Localpoint,RectTransformUtility
然后使用它Canvas.transform.TransformPoint
来找出子UI的确切位置.
public Canvas parentCanvasOfImageToMove;
Vector2 pos;
RectTransformUtility.ScreenPointToLocalPointInRectangle(parentCanvasOfImageToMove.transform as RectTransform, eventData.position, parentCanvasOfImageToMove.worldCamera, out pos);
UIToMove.transform.position = parentCanvasOfImageToMove.transform.TransformPoint(pos);
Run Code Online (Sandbox Code Playgroud)
在其他答案中,拖拽代码看起来比其他拖拽代码更复杂,但它似乎在每个Canvas相机模式下都有效.
检测要拖动的对象:
最简单的方法是创建一个全局变量,您可以使用该变量来保存哪个对象用户想要在OnBeginDrag
函数中拖动,然后您可以拖动该对象OnDrag
.OnEndDrag
调用时将该对象设置为null .
objectToBeDragged = eventData.pointerCurrentRaycast.gameObject;
Run Code Online (Sandbox Code Playgroud)
必须在OnBeginDrag
函数中执行一次,然后将其保存到全局变量中.
您无法在该OnDrag
功能中执行以下操作
if (eventData.pointerCurrentRaycast.gameObject == someOtherUI)
{
someOtherUI....drag
}
Run Code Online (Sandbox Code Playgroud)
即使假设它起作用,它有时也不会.它甚至有时会返回null OnDrag
.这就是必须在OnBeginDrag
函数中完成的原因.
检测并拖动按钮与图像:
检测UI是否只是一个Image
并且拖动一个Image
非常容易.
objectToBeDragged = eventData.pointerCurrentRaycast.gameObject;
Button tempButton = objectToBeDragged.GetComponent<Button>();
Image tempImage = objectToBeDragged.GetComponent<Image>();
Run Code Online (Sandbox Code Playgroud)
如果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>();
Run Code Online (Sandbox Code Playgroud)
如果tempText
是不为空,得到GetComponentInParent
的文本的图像和按钮组件.如果Image
不为null Button
且不为null则为a Button
.
if (tempText != null)
{
tempButton = tempText.GetComponentInParent<Button>();
tempImage = tempText.GetComponentInParent<Image>();
if (tempButton != null && tempImage != null)
{
//This is a Button
}
}
Run Code Online (Sandbox Code Playgroud)
下面是拖动UI图像/面板和按钮的完整脚本.应该拖动的任何按钮都应该放在 UIButtons
数组中,任何应该拖动的面板/图像都应该放在UIPanels
数组中.它将忽略不在Array中的其他UI.
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 };
}
Run Code Online (Sandbox Code Playgroud)
对于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");
}
}
Run Code Online (Sandbox Code Playgroud)