まず第一に、この投稿の他のすべての回答は非常にうまく機能しています。私はこれに長い間取り組んできたので、ここに投稿したいと思いました。他の不要な UI オブジェクトがドラッグされるのを防ぐ方法を追加します。
私の公式の目標は、 を使用せずにこれを行う方法を提供することでしたbool beingDragged = false;
。そのようにすると、どちらがドラッグされているのButton
かわかりません。Image
UI のドラッグ:
を使用して RectTransform のスクリーンポイントをローカル ポイントに変換し、子 UI が正確にどこにあるかを調べるために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);
ドラッグ コードは、他の回答の他のドラッグ コードよりも複雑に見えますが、すべてのキャンバス カメラ モードで動作しているようです。
ドラッグしようとしているオブジェクトの検出:
OnBeginDrag
これを行う最も簡単な方法は、ユーザーが関数にドラッグしたいオブジェクトを保存するために使用できるグローバル変数を作成し、そのオブジェクトをOnDrag
. OnEndDrag
が呼び出されたときにそのオブジェクトを null に設定します。
objectToBeDragged = eventData.pointerCurrentRaycast.gameObject;
これは、OnBeginDrag
関数内で 1 回実行してから、グローバル変数に保存する必要があります。
OnDrag
関数内で次のことを行うことはできません
if (eventData.pointerCurrentRaycast.gameObject == someOtherUI)
{
someOtherUI....drag
}
うまくいくはずなのに、うまくいかないこともあります。中に null を返すことさえありますOnDrag
。そのため、OnBeginDrag
関数で実行する必要があります。
ボタンと画像の検出とドラッグ:
UI が単なる であるかどうかを検出し、Image
をドラッグするのImage
は非常に簡単です。
objectToBeDragged = eventData.pointerCurrentRaycast.gameObject;
Button tempButton = objectToBeDragged.GetComponent<Button>();
Image tempImage = objectToBeDragged.GetComponent<Image>();
そうtempImage
でなく null
、tempButton
ある場合null
、それは画像です。
UI が単に a であるかどうかを検出し、aButton
をドラッグするのButton
は簡単ではありません。ボタンがサイド/エッジでクリックされると、の名前Button
が返されますが、これは問題ありません。しかし、ほとんどの場合、ボタンのインスタンスまたは名前を返さずに(子オブジェクト)を返す途中でa のクリックButton
が発生します。テキストをボタンとして移動することはできません。うまくいきません。Button
Text
objectToBeDragged = eventData.pointerCurrentRaycast.gameObject;
Button tempButton = objectToBeDragged.GetComponent<Button>();
Image tempImage = objectToBeDragged.GetComponent<Image>();
Text tempText = objectToBeDragged.GetComponent<Text>();
null でない場合tempText
は、Text の Image および Button コンポーネントを取得します。が null ではなく、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
}
}
以下は、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 };
}