Эффекты для UI элементов

Несколько интересных эффектов для элементов пользовательского интерфейса. Первый эффект похож на один из популярных эффектов интерфейса различных игр, где элементы интерфейса смещаются навстречу курсору. Второй, повторяет по сути первый режим, но с тем исключением, что сдвиг происходит с небольшой задержкой, для всех элементов в случайном порядке. Третий режим создает эффект, при котором элементы интерфейса как бы прилипают к курсору, но, когда он далеко удаляются, элемент возвращается на своё место. Четвертый эффект, это параллакс для всех элементов в рандомном порядке, движения интерфейса будет как в первом варианте.


Чтобы обеспечит взаимодействие с UI нам понадобится небольшой класс:

using UnityEngine;
using UnityEngine.EventSystems;
[RequireComponent(typeof(RectTransform))]
public class EffectUIComponent : MonoBehaviour, IPointerExitHandler {

    public RectTransform rect { get; set; }
    public Vector3 original { get; set; }
    public float timeout { get; set; }
    public float time { get; set; }
    public Vector3 current { get; set; }
    public bool isSticky { get; set; }
    public Vector3 mouse { get; set; }
    public int index { get; set; }

    void IPointerExitHandler.OnPointerExit(PointerEventData eventData)
    {
        isSticky = true;
        mouse = eventData.position;
    }
}
Данный скрипт мы цепляем на нужные нам объекты UI.

Для переключения и разделения режимов, создаем список:

public enum EffectUIType
{
    Follow, FollowDelay, Sticky, Parallax
}
Теперь класс управления, вешаем его куда угодно:

using UnityEngine;

public class EffectUIControl : MonoBehaviour {

    public EffectUIComponent[] components;
    public float delayMin = .1f;
    public float delayMax = .5f;
    public float followDamping = 3;
    public float delayDamping = .5f;
    public float stickyDamping = 3;
    public float stickyDistance = 30;
    public float parallaxDamping = 10;
    public int parallaxLayers = 5;
    private Vector3 lastPos, lastDir;
    private float magnitude;
    private EffectUIType effect;

    void Start()
    {
        for (int i = 0; i < components.Length; i++)
        {
            components[i].rect = components[i].GetComponent<RectTransform>();
            components[i].original = components[i].rect.position;
        }

        SwitchMode(EffectUIType.Follow); // режим по умолчанию
    }

    void SwitchMode(EffectUIType type)
    {
        effect = type;
        lastPos = Input.mousePosition;
        lastDir = lastPos - Input.mousePosition;
        for (int i = 0; i < components.Length; i++)
        {
            components[i].rect.position = components[i].original;
            components[i].current = components[i].original;
            components[i].time = Random.Range(delayMin, delayMax);
            components[i].index = Random.Range(1, parallaxLayers + 1);
            components[i].timeout = 0;
            components[i].isSticky = false;
        }
    }

    void Follow()
    {
        for (int i = 0; i < components.Length; i++)
        {
            components[i].rect.position += Vector3.Lerp(lastDir, lastPos - Input.mousePosition, followDamping * Time.deltaTime);
        }
    }

    void FollowDelay()
    {
        for (int i = 0; i < components.Length; i++)
        {
            components[i].current += Vector3.Lerp(lastDir, lastPos - Input.mousePosition, followDamping * Time.deltaTime);
            components[i].timeout += Time.deltaTime;
            if (components[i].timeout > components[i].time)
            {
                components[i].rect.position = MoveTowards(components[i].rect.position, components[i].current, delayDamping, out magnitude);

                if (magnitude == 0)
                {
                    components[i].timeout = 0;
                }
            }
        }
    }

    void Sticky()
    {
        for (int i = 0; i < components.Length; i++)
        {
            if (components[i].isSticky)
            {
                components[i].rect.position += Vector3.Lerp(lastDir, Input.mousePosition - lastPos, stickyDamping * Time.deltaTime);

                if (Vector3.Distance(components[i].mouse, Input.mousePosition) > stickyDistance)
                {
                    components[i].isSticky = false;
                }
            }
            else
            {
                components[i].rect.position = Vector3.MoveTowards(components[i].rect.position, components[i].original, stickyDamping * Time.deltaTime);
            }
        }
    }

    void Parallax()
    {
        for (int i = 0; i < components.Length; i++)
        {
            components[i].rect.position += Vector3.Lerp(lastDir, lastPos - Input.mousePosition, parallaxDamping * Time.deltaTime / components[i].index);
        }
    }

    void LateUpdate()
    {
        switch (effect)
        {
            case EffectUIType.Follow:
                Follow();
                break;

            case EffectUIType.FollowDelay:
                FollowDelay();
                break;

            case EffectUIType.Sticky:
                Sticky();
                break;

            case EffectUIType.Parallax:
                Parallax();
                break;
        }

        lastPos = Input.mousePosition;
        lastDir = lastPos - Input.mousePosition;
    }

    Vector3 MoveTowards(Vector3 current, Vector3 target, float maxDistanceDelta, out float magnitude)
    {
        Vector3 a = target - current;
        magnitude = a.magnitude;
        if (magnitude <= maxDistanceDelta || magnitude == 0f)
        {
            magnitude = 0;
            return target;
        }
        return current + a / magnitude * maxDistanceDelta;
    }

#if UNITY_EDITOR
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.F9))
        {
            SwitchMode(EffectUIType.Follow);
        }
        else if (Input.GetKeyDown(KeyCode.F10))
        {
            SwitchMode(EffectUIType.FollowDelay);
        }
        else if (Input.GetKeyDown(KeyCode.F11))
        {
            SwitchMode(EffectUIType.Sticky);
        }
        else if (Input.GetKeyDown(KeyCode.F12))
        {
            SwitchMode(EffectUIType.Parallax);
        }
    }
#endif
}
Все объекты на которые ранее был добавлен скрипт EffectUIComponent, нужно перетащить в массив components. Переключения эффектов делается клавишами F9, F10, F11, F12 - это работает только в редакторе Юнити, для теста.

Скачать демо:

Внимание! Посетители, находящиеся в группе Гости, не могут скачивать файлы.
Тестировалось на: Unity 2018.2.12

Комментариев 2

Офлайн
datodavita1212 16 октября 2018
krutoi sait gotovie proekti vabshe eta shedevralna.

1) vkajdom teme pastavte link proektaa chtomi mi magli ivo zagruzit nu gotovi proekt
2) vskriptax delaite komentarii chto dlia chevo i tagdali
3) zagruzite vnachale posta pakazatelni video chtobi uvidet rezultat svaimi glazami

vobshem bravo :) i spasiba vam dlia etava s aita
Офлайн
Liphanes 22 октября 2018
Цитата: datodavita1212
krutoi sait gotovie proekti vabshe eta shedevralna.

1) vkajdom teme pastavte link proektaa chtomi mi magli ivo zagruzit nu gotovi proekt
2) vskriptax delaite komentarii chto dlia chevo i tagdali
3) zagruzite vnachale posta pakazatelni video chtobi uvidet rezultat svaimi glazami

vobshem bravo :) i spasiba vam dlia etava s aita

Чуть не помер пока прочитал))
Информация
Посетители, находящиеся в группе Гости, не могут оставлять комментарии к данной публикации.
  • Дешевый хостинг
  • Яндекс.Метрика