Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/unity3d/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Unity3D UI,是否计算拖动项目的位置?_C#_Unity3d_Unity3d Ui - Fatal编程技术网

C# Unity3D UI,是否计算拖动项目的位置?

C# Unity3D UI,是否计算拖动项目的位置?,c#,unity3d,unity3d-ui,C#,Unity3d,Unity3d Ui,现在,在Unity中拖动UI元素非常容易:制作一些UI项。添加组件->事件->事件触发器。点击下面的脚本。单击以添加四个明显的触发器。你完了 不过 我完全迷失在指针坐标和用户界面坐标之间的关系中(如RectTransform等所示) 在下面的DragIt中:你他妈的怎么能在手指下正确移动UI面板 假设您有一个大面板,面板上有十个UIButton,按钮上有Dragster。RectTransform坐标和鼠标指针之间的关系是什么 简言之,如何在下面的DragIt()中移动其中一个按钮 我会让你的脚

现在,在Unity中拖动UI元素非常容易:制作一些UI项。添加组件->事件->事件触发器。点击下面的脚本。单击以添加四个明显的触发器。你完了

不过

我完全迷失在指针坐标用户界面坐标之间的关系中(如RectTransform等所示)

在下面的
DragIt
中:你他妈的怎么能在手指下正确移动UI面板

假设您有一个大面板,面板上有十个UIButton,按钮上有
Dragster
。RectTransform坐标和鼠标指针之间的关系是什么

简言之,如何在下面的DragIt()中移动其中一个按钮


我会让你的脚本实现拖动接口

公共类Dragster:MonoBehavior、iRegindragHandler、IENDragHandler、IDragHandler

这将使您的
DragIt
函数

public void OnDrag(PointerEventData eventData)
{
    transform.position += (Vector3)eventData.delta;
}
允许您访问该事件的增量(鼠标移动量),以便能够移动对象

如果您仍然希望使用EventTrigger组件(不太喜欢的方式),只需将
DragIt
函数更改为
DragIt(PointerEventData eventData)
,并使用触发器下拉列表中的Dynamic EvenData选项来接收PointerEventData以访问增量信息


这实际上是一个基于Uri和Colton代码的拖放“UnityEngine.UI”项的完整解决方案。复制粘贴即可

为Unity UI、wtt Colton和Uri提供无需大脑的完美拖放功能,复制粘贴效果令人惊叹:
使用UnityEngine;
使用UnityEngine.UI;
使用UnityEngine.EventSystems;
公共类不可拖动:单一行为,
IbRegindRagHandler,IDragHandler,IendRagHandler,IDropHandler
{
公众形象幽灵;
//注意:不要试图拖动实际项目:这不值得麻烦。
//出现了一个问题,你不能把它放在上面(正如你所希望的那样)
//视觉上),并且仍然很容易得到滴水。始终使用幽灵。
//即使拖动时希望“原始不可见”,
//只要把它藏起来,然后用鬼魂。一切都是非常可怕的
//如果不移动原件,则更容易。
无效唤醒()
{
ghost.raycastTarget=false;
//(以防万一你忘了在编辑器里做那件事)
ghost.enabled=false;
}
公共void OnBeginDrag(PointerEventData事件数据)
{
ghost.transform.position=transform.position;
ghost.enabled=true;
}
public void OnDrag(PointerEventData事件数据)
{
ghost.transform.position+=(Vector3)eventData.delta;
}
公共无效OnEndRag(PointerEventData事件数据)
{
ghost.enabled=false;
}
公共无效OnDrop(PointerEventData数据)
{
GameObject fromItem=data.pointerDrag;
if(data.pointerDrag==null)返回;//(永远不会发生)
undraggable d=fromItem.GetComponent();
如果(d==null)
{
//意味着与我们的系统无关的东西被拖了出来。
//例如,只是一个不相关的滚动区域,等等。
//完全忽略这些。
返回;
//注意,如果非常罕见,您有多个“系统”
//对于同一屏幕上的无法拖动的项目,请注意
//区分它们!示例解决方案,检查父母是否相同。
}
Log(“将”+fromtime.name+“删除到”+gameObject.name);
//您的代码可能如下所示:
YourThings fromThing=fromItem.GetComponent().info;
YourThings untoThing=gameObject.GetComponent().info;
你的老板反对。从一件事到另一件事(从一件事到另一件事);
}
}

对于拖动内容,我只需执行以下操作:

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");
    
    }
}
下面是完全相同的令人惊叹的URIPOPOV代码,其中包含两个简单的功能,拖动时始终需要这些功能:

// allow dragging with two basic problem fixes:
// - limit drag to the parent box
// - don't "jump" based on where you hold down
100%测试:

using UnityEngine;
using UnityEngine.EventSystems;

public class AmazingUPDrag : MonoBehaviour,
               IBeginDragHandler, IDragHandler, IEndDragHandler
{
    Vector2 dragOffset = Vector2.zero;
    Vector2 limits = Vector2.zero;

    public void OnBeginDrag(PointerEventData eventData)
    {
        dragOffset = eventData.position - (Vector2)transform.position;
        limits = transform.parent.GetComponent<RectTransform>().rect.max;
    }

    public void OnDrag(PointerEventData eventData)
    {
        transform.position = eventData.position - dragOffset;
        var p = transform.localPosition;
        if (p.x < -limits.x) { p.x = -limits.x; }
        if (p.x > limits.x) { p.x = limits.x; }
        if (p.y < -limits.y) { p.y = -limits.y; }
        if (p.y > limits.y) { p.y = limits.y; }
        transform.localPosition = p;
    }

    public void OnEndDrag(PointerEventData eventData)
    {
        dragOffset = Vector2.zero;
    }
}
使用UnityEngine;
使用UnityEngine.EventSystems;
公共课:单一行为,
IbRegindRagHandler、IDragHandler、IENDRagHandler
{
Vector2 dragOffset=Vector2.0;
Vector2极限=Vector2.0;
公共void OnBeginDrag(PointerEventData事件数据)
{
dragOffset=eventData.position-(Vector2)transform.position;
限制=transform.parent.GetComponent().rect.max;
}
public void OnDrag(PointerEventData事件数据)
{
transform.position=eventData.position-dragOffset;
var p=transform.localPosition;
如果(p.x<-limits.x){p.x=-limits.x;}
如果(p.x>limits.x){p.x=limits.x;}
如果(p.y<-limits.y){p.y=-limits.y;}
如果(p.y>limits.y){p.y=limits.y;}
transform.localPosition=p;
}
公共无效OnEndRag(PointerEventData事件数据)
{
dragOffset=矢量2.0;
}
}

首先,这篇文章中的所有其他答案都很好。我做了这么长时间,只想把它贴在这里。它增加了一种防止其他不需要的UI对象被拖动的方法

我的官方目标是提供一种不使用
boolbeingdrable=false的方法。如果你这样做的话,你就不知道哪个
按钮或
图像被拖动了

拖动UI

借助
RectTransformUtility
将屏幕点转换为RectTransform中的本地点,然后使用
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);
在其他答案中,拖动代码看起来比其他拖动代码更复杂,但它似乎在每个画布相机模式下都能工作

检测将要拖动的对象using UnityEngine; using UnityEngine.EventSystems; public class AmazingUPDrag : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler { Vector2 dragOffset = Vector2.zero; Vector2 limits = Vector2.zero; public void OnBeginDrag(PointerEventData eventData) { dragOffset = eventData.position - (Vector2)transform.position; limits = transform.parent.GetComponent<RectTransform>().rect.max; } public void OnDrag(PointerEventData eventData) { transform.position = eventData.position - dragOffset; var p = transform.localPosition; if (p.x < -limits.x) { p.x = -limits.x; } if (p.x > limits.x) { p.x = limits.x; } if (p.y < -limits.y) { p.y = -limits.y; } if (p.y > limits.y) { p.y = limits.y; } transform.localPosition = p; } public void OnEndDrag(PointerEventData eventData) { dragOffset = Vector2.zero; } }
public Canvas parentCanvasOfImageToMove;
Vector2 pos;
RectTransformUtility.ScreenPointToLocalPointInRectangle(parentCanvasOfImageToMove.transform as RectTransform, eventData.position, parentCanvasOfImageToMove.worldCamera, out pos);
UIToMove.transform.position = parentCanvasOfImageToMove.transform.TransformPoint(pos);
objectToBeDragged = eventData.pointerCurrentRaycast.gameObject;
if (eventData.pointerCurrentRaycast.gameObject == someOtherUI)
{
   someOtherUI....drag
}
objectToBeDragged  = eventData.pointerCurrentRaycast.gameObject;
Button tempButton = objectToBeDragged.GetComponent<Button>();
Image tempImage = objectToBeDragged.GetComponent<Image>();
objectToBeDragged  = eventData.pointerCurrentRaycast.gameObject;
Button tempButton = objectToBeDragged.GetComponent<Button>();
Image tempImage = objectToBeDragged.GetComponent<Image>();
Text tempText = objectToBeDragged.GetComponent<Text>();
if (tempText != null)
{
    tempButton = tempText.GetComponentInParent<Button>();
    tempImage = tempText.GetComponentInParent<Image>();
    if (tempButton != null && tempImage != null)
    {
        //This is a Button
    }
}
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 };
}
using UnityEngine.EventSystems;

public class SomeObject : MonoBehaviour, IBeginDragHandler, IDragHandler
{
  private Canvas parentCanvas;
  private Vector3 moveOffset;

  void Start()
  {
      // get the "nearest Canvas"
      parentCanvas = GetComponentsInParent<Canvas>()[0];
      // you could get the Camera of this Canvas here as well and like @ina suggests add a null check for that and otherwise use Camera.Main
  }
  public void OnBeginDrag(PointerEventData eventData)
  {

      //For Offset Position so the object won't "jump" to the mouse/touch position
      RectTransformUtility.ScreenPointToLocalPointInRectangle(parentCanvas.transform as RectTransform, eventData.position, parentCanvas.worldCamera, out Vector2 pos);
      moveOffset = transform.position - parentCanvas.transform.TransformPoint(pos);

  }

  public void OnDrag(PointerEventData eventData)
  {
      RectTransformUtility.ScreenPointToLocalPointInRectangle(parentCanvas.transform as RectTransform, eventData.position, parentCanvas.worldCamera, out Vector2 pos);
      transform.position = parentCanvas.transform.TransformPoint(pos) + moveOffset;
  }
}