最近では、UnityでUI要素をドラッグするのは非常に簡単です。いくつかのUIアイテムを作成します。コンポーネント->イベント-> イベントトリガーを追加します。以下のスクリプトにドロップしてください。クリックして、4つの明白なトリガーを追加します。完了です。
しかしながら。
ポインター座標とI座標(RectTransformなどで見られる)の関係に完全に夢中になっています。
以下のDragIt
で:UIパネルを指の下で正しく移動するにはどうすればよいですか?
大きなパネルが1つあり、そのパネルに10個のUIButtonがあり、ボタンにDragster
が付いているとします。 RectTransformの座標とマウスポインターの関係は何ですか?.
簡単に言うと、下のDragIt()でボタンの1つをどのように移動しますか?
/* 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);
}
}
ドラッグのものについては、これを行うだけです:
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");
}
}
スクリプトにドラッグインターフェイスを実装させます
_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を受け取ります
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);
}
}
_
まず、この投稿の他のすべての回答は非常にうまく機能しています。私はこれに長い間取り組んでおり、ここに投稿したかっただけです。他の不要なUIオブジェクトがドラッグされるのを防ぐ方法を追加します。
私の公式の目標は、bool beingDragged = false;
を使用せずにこれを行う方法を提供することでした。このようにすると、ドラッグされているButton
またはImage
がわかりません。
Iのドラッグ:
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);
ドラッグコードは、他の回答では他のドラッグコードよりも複雑に見えますが、すべてのCanvasカメラモードで機能しているようです。
ドラッグされようとしているオブジェクトの検出:
これを行う最も簡単な方法は、ユーザーがOnBeginDrag
関数にドラッグしたいオブジェクトを保存するために使用できるグローバル変数を作成し、そのオブジェクトをOnDrag
にドラッグすることです。 OnEndDrag
が呼び出されたときに、そのオブジェクトをnullに設定します。
objectToBeDragged = eventData.pointerCurrentRaycast.gameObject;
これは、OnBeginDrag
関数で一度実行してから、グローバル変数に保存する必要があります。
OnDrag
関数では次のことはできません
if (eventData.pointerCurrentRaycast.gameObject == someOtherUI)
{
someOtherUI....drag
}
動作することを想定していますが、動作しない場合もあります。 OnDrag
の実行中にnullが返されることもあります。これがOnBeginDrag
関数で行わなければならない理由です。
ボタンとイメージの検出とドラッグ:
UIがImage
であるかどうかの検出とImage
のドラッグは非常に簡単です。
objectToBeDragged = eventData.pointerCurrentRaycast.gameObject;
Button tempButton = objectToBeDragged.GetComponent<Button>();
Image tempImage = objectToBeDragged.GetComponent<Image>();
tempImage
がnotnull
で、tempButton
がnull
の場合、それは画像です。
UIがButton
であるかどうかの検出とButton
のドラッグは[〜#〜] not [〜#〜]簡単です。ボタンがside/Edgeでクリックされると、Button
の名前が返されますが、これは問題ありません。しかし、ほとんどの場合、Button
のクリックはButton
の-middleで発生しますnotはインスタンスまたは名前を返しますButtonの代わりにText
(Child Object)を返します。あなたは[〜#〜]できません[〜#〜]テキストをボタンとして移動します。うまくいきません。
objectToBeDragged = eventData.pointerCurrentRaycast.gameObject;
Button tempButton = objectToBeDragged.GetComponent<Button>();
Image tempImage = objectToBeDragged.GetComponent<Image>();
Text tempText = objectToBeDragged.GetComponent<Text>();
tempText
がnot nullの場合、テキストの画像およびボタンコンポーネントのGetComponentInParent
を取得します。 Image
がnullでなく、Button
がnullでない場合は、Button
です。
if (tempText != null)
{
tempButton = tempText.GetComponentInParent<Button>();
tempImage = tempText.GetComponentInParent<Image>();
if (tempButton != null && tempImage != null)
{
//This is a Button
}
}
以下は、UI画像/パネルとボタンをドラッグする完全なスクリプトです。ドラッグする必要のあるボタンはUIButtons
配列に配置し、ドラッグする必要のあるパネル/画像はUIPanels
配列に配置する必要があります。配列に含まれていない他の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 };
}