- Home /
How to make UI element to be draggable within screen borders
Hi,
I am trying to create a script that I want to attach to any UI element to make them draggable, but only within the screen borders. My monitor has a default 16:9 aspect ratio and the below script only works with that value, but when I change it to something different (e.g. 5:4, or 16:10) in the editor, the area where the UI elements can move does not fully fill the screen. Is there a proper way to handle this from script?
All UI elements added to the same Canvas. The Canvas is set to Screen Space - Overlay and it has a Canvas scaler with a reference resolution of 1920x1080 (so 16:9), Match width or height with 0.5 match. I tried setting the UI elements' anchors to both the edges of the screen and the edges of their rectangle, but seemingly there is no difference regarding the draggable action.
p.s.: The only thing I noticed that incorrect is the RectTransform.rect value after I change the aspect ratio.
using UnityEngine;
public class UIElementDragAndDrop : MonoBehaviour
{
float OffsetX;
float OffsetY;
float Width;
float Height;
float LastMousePosX;
float LastMousePosY;
float NewMousePosX;
float NewMousePosY;
float ScaleX;
float ScaleY;
RectTransform RectTransform;
public void Start()
{
RectTransform = GetComponent<RectTransform>();
}
public void BeginDrag()
{
//Calculate scaling for windowed mode.
ScaleX = Display.main.renderingWidth * 1.0f / Screen.currentResolution.width;
ScaleY = Display.main.renderingHeight * 1.0f / Screen.currentResolution.height;
//Get the current size of the UI element as it can be different when changing aspect ratio in the editor.
Width = RectTransform.rect.width * ScaleX;
Height = RectTransform.rect.height * ScaleY;
//Move UI element to the front.
transform.SetAsLastSibling();
//Save mouse position, so OnDrag will not cause the control to jump.
LastMousePosX = Input.mousePosition.x;
LastMousePosY = Input.mousePosition.y;
}
public void OnDrag()
{
//Storing new mouse position.
NewMousePosX = Input.mousePosition.x;
NewMousePosY = Input.mousePosition.y;
//Difference to previous position.
OffsetX = NewMousePosX - LastMousePosX;
OffsetY = NewMousePosY - LastMousePosY;
float resultX = transform.position.x + OffsetX;
float resultY = transform.position.y + OffsetY;
if (resultX < 0.0f)
resultX = 0.0f;
if (resultX > Display.main.renderingWidth - Width)
resultX = Display.main.renderingWidth - Width;
if (resultY < 0.0f)
resultY = 0.0f;
if (resultY > Display.main.renderingHeight - Height)
resultY = Display.main.renderingHeight - Height;
transform.position = new Vector3(
resultX,
resultY,
transform.position.z);
LastMousePosX = NewMousePosX;
LastMousePosY = NewMousePosY;
}
}
Y dont you use the drag handler event system?and how is it possible to drag out side the screen so i dont get y u are trying to clamp the movement.
This is done via the drag events. I changed the width/height check to resultX = $$anonymous$$athf.Clamp(resultX, 0.0f, Display.main.renderingWidth - Width); resultY = $$anonymous$$athf.Clamp(resultY, 0.0f, Display.main.renderingHeight - Height); but it is the same logic that I had before in shorter way. I think the problem is the calculation if Width and Height, because the values are not what I would expect when I change the aspect ratio.
Answer by Happeloy · May 19, 2018 at 07:20 PM
You don't need to write this yourself! There is an UI element called Scroll View, that does all this for you!
Here's a Unity Tutorial about it: https://unity3d.com/learn/tutorials/topics/user-interface-ui/scroll-view
Edit: sorry, I believe I misunderstood your question. I'm gonna leave it here anyway, might be helpful.
No problem and thanks for trying. Basically I am just trying to make my UI elements movable, so the player could rearrange the controls, but the RectTransform.rect gives very, very strange values on different aspect ratios.
Answer by Vionix · May 20, 2018 at 02:46 AM
this is how i do the drag in unity and it very well remains within screen
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class Dragscript : MonoBehaviour,IBeginDragHandler,IDragHandler,IEndDragHandler {
public static Vector3 move;
Vector3 initialpos;
Vector3 distance;
float speed=0.2f;
void Start()
{
move = Vector3.zero;
}
#region IBeginDragHandler implementation
public void OnBeginDrag (PointerEventData eventData)
{
initialpos = transform.position;
move = Vector3.zero;
}
#endregion
#region IDragHandler implementation
public void OnDrag (PointerEventData eventData)
{
if (Input.mousePosition.x < Screen.width / 2 && Input.mousePosition.y < Screen.height/2) {
distance = Input.mousePosition - initialpos;
distance = Vector3.ClampMagnitude (distance, 45 * Screen.width / 708);
transform.position = initialpos + distance;
Vector3 move1 = distance.normalized;
move.x = move1.x * speed;
move.z = move1.y * speed;
}
}
#endregion
#region IEndDragHandler implementation
public void OnEndDrag (PointerEventData eventData)
{
move = Vector3.zero;
transform.position = initialpos;
}
#endregion
}