Jump to content
Sign in to follow this  
Константин Орлов

Unity: UI шпаргалка по скриптам интерфейса

Recommended Posts

Как сделать, чтобы в Unity окно можно было перетаскивать?

 

Перетаскивание окон. Это работает не только с окнами, но и любыми элементами интерфейса (UI). Нужно просто реализовать интерфейс (термин из C#) и событие. Вот самый простой пример:

Спойлер

 


using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems; //обязательно для работы с системой событий

public class TestDrag : MonoBehaviour, IDragHandler //интерфейсы
{
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // в процессе перетаскивания
    public void OnDrag(PointerEventData eventData)
    {
        // окно движется вместе с мышкой
        transform.position = Input.mousePosition;
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

 

 

 

Вешаете этот скрипт на UI-элемент в Юнити, и теперь при перетягивании его мышкой он будет менять свое положение на экране.

Share this post


Link to post
Share on other sites

Дочерние окна тоже цепляются мышкой, что делать?

 

Перетаскивание окон в Юнити можно сделать круче и исправить некоторые недостатки, что есть в движке. Например, если сделать у окна лишь определенную зону, за которую можно цепляться (например, заголовок окна), и у этой зоны сделать дочерним объект (любой элемент, например, Panel), то панель тоже будет цепляться курсором, что далеко не всегда нужно. Исправляется это так:

Задача: сделать так, чтобы только один элемент (заголовок) был зоной для перетаскивания, а его дочерние UI-элементы нет. Решение: вешаем этот скрипт на нужный элемент для перетаскивания, а также на тот, который перетаскивать не надо (он будет перетаскиваться вместе с родительским (заголовком)), но у дочернего убираем галочку на isDragging:
 

Спойлер

 


using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems; //обязательно для работы с системой событий

public class Window : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler //интерфейсы
{

    //стартовая позиция мыши при начале перетаскивания
    //нужна, чтобы окно сразу не дергалось центрируясь по курсору мышки
    //а плавно меняла положение вслед за курсором
    private Vector3 mouseStartingPos;

    //поддается ли перетаскиванию (цепляет ли его курсор)
    public bool isDragging = true;

    //сколько пикселей от конца экрана безопасная зона, куда будет возвращено окно
    //при перетаскивании за край экрана
    int pixeSafeZone = 20;

    //начало перетаскивания
    public void OnBeginDrag(PointerEventData eventData)
    {
        //запоминаем где была мыш на начале перетаскивания
        mouseStartingPos = Input.mousePosition;
    }

    // в процессе перетаскивания (вызывается каждый раз при изменении положении мышки)
    public void OnDrag(PointerEventData eventData)
    {
        //если окно может цеплять курсор (перетаскиваемое)
        if (isDragging)
        { 
        //позиция окна изменяется соответственно тому, как изменилась
        //позиция мышки в процессе перетаскивания. При каждом движении вычисляем
        //разницу между прошлым и текущим положением мышки и применяем ее к окну
        transform.position -= mouseStartingPos - Input.mousePosition;
        //запоминаем текущее положение
        mouseStartingPos = Input.mousePosition;
        }
    }



    //в конце перетаскивания
    public void OnEndDrag(PointerEventData eventData)
    {
        //не позволить окнам выходить за разрешение экрана
        CheckOutScreen();

    }

    //не позволяет окнам выходить за разрешение экрана
    private void CheckOutScreen ()
    {
        //если окно вышло по иску за пределы экрана вправо
        if (transform.position.x > Screen.width)
        {
            //возвращаем его в пределы экрана
            transform.position = new Vector3(Screen.width - pixeSafeZone, transform.position.y);
        }
        //если окно вышло по иску за пределы экрана влево
        else if (transform.position.x <= 0)
        {
            //возвращаем его в пределы экрана
            transform.position = new Vector3(pixeSafeZone, transform.position.y);
        }

        //если окно вышло по игреку за пределы экрана вправо
        if (transform.position.y > Screen.height)
        {
            //возвращаем его в пределы экрана
            transform.position = new Vector3(transform.position.x, Screen.height - pixeSafeZone);
        }
        //если окно вышло по игреку за пределы экрана влево
        else if (transform.position.y <= 0)
        {
            //возвращаем его в пределы экрана
            transform.position = new Vector3(transform.position.x, pixeSafeZone);
        }
    }

    void Update()
    {

    }

    void Start()
    {
    }
}

 

 

 

 

Окно в Unity вышло за пределы экрана, как вернуть назад?


Вышеописанный скрипт также содержит метод, который возвращает в зону разрешения экрана окно, если оно вышло за пределы координат. Срабатывает проверка автоматически при завершении перетаскивания.

Share this post


Link to post
Share on other sites

Как масштабировать UI в Юнити под разрешение экрана?

 

В Canvas необходимо выбрать режим Scale With Screen Size. На любом канвасе автоматически есть компонент Canvas Scaler, режим выставляется там. После этого все дочерние элементы пользовательского интерфейса будут уменьшаться пропорционально Y-разрешению экрана. В самих элементах, возможно, нужно будет поколдовать с RectTransform, точно не помню, вроде что-то с Pivot и привязкой (попробуйте привязать изначально к верху середины).

Share this post


Link to post
Share on other sites

Как изменить позицию UI-элемента (окна, кнопки т.п.) в Юнити?

 

gameObject.transform.position = new Vector2(transform.position.x + 190, transform.position.y);

Пример кода, который по иксу двигает элемент пользовательского интерфейса на 190 пикселей. Y остается таким же (так как туда вводится та же координата, которой Y сейчас соответствует).

Но при смене разрешения такой подход может привести к тому, что элемент окажется за экраном, так как это позиция в пикселях.

 

Второй способ перетаскивания в UI

 

Есть второй способ, который считывает движение мыши (я так понимаю мыши передает лишь +1 либо -1), но окно движется очень медленно и ускорение мышки влияет так, что окно отстает:

transform.position += new Vector3(Input.GetAxis("Mouse X"), Input.GetAxis("Mouse Y"));

Нормальный способ перетащить окно в Unity

 

А вот это похоже на что-то вменяемое, нужно реализовать интерфейс (ищите инфу что за интерфейсы по началу перетаскивания, в процессе и в конце):

public void OnDrag(PointerEventData eventData)
    {
        transform.position += (Vector3)eventData.delta;
    }

 

Share this post


Link to post
Share on other sites

Не позволяет окнам выходить за разрешение экрана

Алгоритм не самый удачный, но сохраню это здесь, вдруг приходится.

    //сколько пикселей от конца экрана безопасная зона, куда будет возвращено окно
    //при перетаскивании за край экрана
    int pixeSafeZone = 35;

//скрипт должен быть на объекте, и вызываться должна эта функция дял проверки выхода за экран
private void CheckOutScreen()
    {
        #region //не позволяет окнам выходить за разрешение экрана
        //если окно вышло по иску за пределы экрана вправо
        if (transform.position.x > Screen.width)
        {
            //возвращаем его в пределы экрана
            transform.position = new Vector3(Screen.width - pixeSafeZone, transform.position.y);
        }
        //если окно вышло по иску за пределы экрана влево
        else if (transform.position.x <= 0)
        {
            //возвращаем его в пределы экрана
            transform.position = new Vector3(pixeSafeZone, transform.position.y);
        }

        //если окно вышло по игреку за пределы экрана вверх
        if (transform.position.y > Screen.height)
        {
            //возвращаем его в пределы экрана
            transform.position = new Vector3(transform.position.x, Screen.height - pixeSafeZone);
        }
        //если окно вышло по игреку за пределы экрана вниз
        else if (transform.position.y <= 0)
        {
            //возвращаем его в пределы экрана
            transform.position = new Vector3(transform.position.x, pixeSafeZone);
        }
    }

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×