c# - tutorial - unity 3d ui
UI de Unity3D, cálculo de posición arrastrando un elemento? (3)
En primer lugar, todas las otras respuestas en esta publicación están funcionando muy bien. Trabajé en esto durante tanto tiempo y solo quería publicarlo aquí. Agrega una forma de evitar que otros objetos de IU no deseados sean arrastrados.
Mi objetivo oficial era proporcionar una forma de hacer esto sin usar
bool beingDragged = false;
.
Simplemente no sabrá qué
Button
o
Image
se está arrastrando si lo hace así.
Arrastrando la IU :
Convierta Screenpoint a punto local en RectTransform con la ayuda de
RectTransformUtility
luego use
Canvas.transform.TransformPoint
para averiguar dónde está exactamente la interfaz de usuario secundaria.
public Canvas parentCanvasOfImageToMove;
Vector2 pos;
RectTransformUtility.ScreenPointToLocalPointInRectangle(parentCanvasOfImageToMove.transform as RectTransform, eventData.position, parentCanvasOfImageToMove.worldCamera, out pos);
UIToMove.transform.position = parentCanvasOfImageToMove.transform.TransformPoint(pos);
El código de arrastre parece más complicado que otro código de arrastre en otras respuestas, pero parece estar funcionando en todos los modos de cámara Canvas.
Detectar qué objeto está a punto de ser arrastrado :
La forma más fácil de hacerlo es crear una variable global que pueda usar para guardar qué objeto desea arrastrar el usuario en la función
OnBeginDrag
, luego puede arrastrar ese objeto en
OnDrag
.
Establezca ese objeto en nulo cuando se llama a
OnEndDrag
.
objectToBeDragged = eventData.pointerCurrentRaycast.gameObject;
Esto debe hacerse una vez en la función
OnBeginDrag
luego guardarse en una variable global.
No puede hacer lo siguiente en la función
OnDrag
if (eventData.pointerCurrentRaycast.gameObject == someOtherUI)
{
someOtherUI....drag
}
Aunque se supone que funciona, a veces no lo hace.
Incluso devuelve nulo a veces durante
OnDrag
.
Es por eso que debe hacerse en la función
OnBeginDrag
.
Detectar y arrastrar la imagen del botón Vs :
Detectar si la interfaz de usuario es solo una
Image
y arrastrar una
Image
es muy fácil.
objectToBeDragged = eventData.pointerCurrentRaycast.gameObject;
Button tempButton = objectToBeDragged.GetComponent<Button>();
Image tempImage = objectToBeDragged.GetComponent<Image>();
Si
tempImage
no
es
null
y
tempButton
es
null
entonces esa es una imagen.
Detectar si la interfaz de usuario es solo un
Button
y arrastrar un
Button
NO
es fácil.
Cuando se hace clic en un botón en el
lateral / borde
, se devuelve el nombre del
Button
lo cual está bien.
Pero la mayoría de las veces, un clic en un
Button
ocurre en el
medio
del
Button
que
no
devuelve la instancia o el nombre del botón, sino que devuelve el
Text
(objeto secundario).
NO PUEDE
mover un texto como un botón.
No funcionará
objectToBeDragged = eventData.pointerCurrentRaycast.gameObject;
Button tempButton = objectToBeDragged.GetComponent<Button>();
Image tempImage = objectToBeDragged.GetComponent<Image>();
Text tempText = objectToBeDragged.GetComponent<Text>();
si
tempText
no
es nulo, obtenga el
GetComponentInParent
of Image and Button del texto.
Si la
Image
no es nula y el
Button
no es nulo, entonces es un
Button
.
if (tempText != null)
{
tempButton = tempText.GetComponentInParent<Button>();
tempImage = tempText.GetComponentInParent<Image>();
if (tempButton != null && tempImage != null)
{
//This is a Button
}
}
A continuación se muestra la secuencia de comandos completa de arrastrar la imagen / panel de UI y el botón.
Cualquier botón que deba arrastrarse debe colocarse en la matriz
UIButtons
y cualquier Panel / Imagen que deba arrastrarse debe colocarse en la matriz
UIPanels
.
Ignorará otras IU que no están en la matriz.
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 };
}
En estos días es increíblemente fácil arrastrar elementos de la interfaz de usuario en Unity: crea algunos elementos de la interfaz de usuario. Agregar componente -> Evento -> Activador de eventos . Suelta el guión a continuación. Haga clic para agregar los cuatro desencadenantes obvios. Ya terminaste
Sin embargo.
Estoy totalmente perdido en la relación entre las coordenadas del puntero y las coordenadas de la interfaz de usuario (como se ve en RectTransform, etc.).
En
DragIt
continuación: ¿cómo diablos mueves un panel de interfaz de usuario correctamente debajo del dedo?
Digamos que tiene un panel grande, con diez UIButton sentado en el panel con
Dragster
en los botones.
¿Cuál es la relación entre las coordenadas RectTransform y el puntero del mouse ...
en resumen, ¿cómo mueve uno de los botones en DragIt () a continuación?
/* 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);
}
}
Haría que tu script implemente las interfaces de arrastre
public class Dragster:MonoBehaviour,IBeginDragHandler, IEndDragHandler, IDragHandler
Lo que hará que su función
DragIt
convierta
public void OnDrag(PointerEventData eventData)
{
transform.position += (Vector3)eventData.delta;
}
dándole acceso al delta de ese evento (cuánto se ha movido el mouse) para poder mover su objeto.
Si aún prefiere usar el componente EventTrigger (forma menos preferida), solo necesita cambiar su función
DragIt
a
DragIt(PointerEventData eventData)
y usar la opción Dynamic EvenData en el menú desplegable para que el activador reciba el PointerEventData para acceder al delta información
Aquí hay una solución total y completa para arrastrar y soltar elementos ''UnityEngine.UI`, basado en el código de Uri & Colton. Solo copia y pega.
Asombroso copiar y pegar sin complicaciones, arrastrar y soltar perfecto para Unity UI, wtt Colton y Uri:
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);
}
}
Para dragar cosas solo hago esto:
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");
}
}