Исправить мультитач ScrollRect в Unity? - PullRequest
2 голосов
/ 20 мая 2019

В настоящее время ScrollRect чрезвычайно глючит, когда речь заходит о мультитач на мобильных устройствах.

Если вы попробуете это сами, вы увидите, что всякий раз, когда вы кладете два пальца на экран, контентбудет прыгать и выдавать неожиданное поведение.

Есть ли какие-либо решения для этого?В настоящее время это - единственное решение, которое я нашел, но в некоторых случаях оно по-прежнему содержит ошибки и, что более важно, не определяет среднюю позицию ввода (или MultiTouchPosition) для всех ваших пальцев на экране.

Вот моя модифицированная версия сценария MultiTouchScrollRect.cs из UnityUIExtensions битбакета, но он каждый раз выскакивает, когда я указываю на экран следующим пальцем:

using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

public class MultiTouchScrollRect : ScrollRect
{
    private int minimumTouchCount = 1, maximumTouchCount = 2, pointerId = -100;

    public Vector2 MultiTouchPosition
    {
        get
        {
            Vector2 position = Vector2.zero;
            for (int i = 0; i < Input.touchCount && i < maximumTouchCount; i++)
            {
                position += Input.touches[i].position;
            }
            position /= ((Input.touchCount <= maximumTouchCount) ? Input.touchCount : maximumTouchCount);
            return position;
        }
    }

    public override void OnBeginDrag(PointerEventData eventData)
    {
        if (Input.touchCount >= minimumTouchCount)
        {
            pointerId = eventData.pointerId;
            eventData.position = MultiTouchPosition;
            base.OnBeginDrag(eventData);
        }
    }
    public override void OnDrag(PointerEventData eventData)
    {
        if (Input.touchCount >= minimumTouchCount)
        {
            eventData.position = MultiTouchPosition;
            if (pointerId == eventData.pointerId)
            {
                base.OnDrag(eventData);
            }
        }
    }
    public override void OnEndDrag(PointerEventData eventData)
    {
        if (Input.touchCount >= minimumTouchCount)
        {
            pointerId = -100;
            eventData.position = MultiTouchPosition;
            base.OnEndDrag(eventData);
        }
    }
}

Спасибоза ваше время!

Ответы [ 2 ]

0 голосов
/ 21 июля 2019

Для тех, кто заинтересован, это расширенный класс ScrollRect, который я написал и который устраняет проблему:

using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

namespace DanielLochner.Assets.SimpleZoom
{
    public class MultiTouchScrollRect : ScrollRect
    {
        #region Fields
        private int minimumTouchCount = 1, maximumTouchCount = 2, initialTouchCount = 0;
        #endregion

        #region Properties
        public Vector2 MultiTouchPosition
        {
            get
            {
                Vector2 position = Vector2.zero;
                for (int i = 0; i < Input.touchCount && i < maximumTouchCount; i++)
                {
                    position += Input.touches[i].position;
                }
                position /= ((Input.touchCount <= maximumTouchCount) ? Input.touchCount : maximumTouchCount);

                return position;
            }
        }
        #endregion

        #region Methods
        private void Update()
        {
            if (SystemInfo.deviceType == DeviceType.Handheld || UnityEditor.EditorApplication.isRemoteConnected)
            {
                if (Input.touchCount > 0)
                {
                    if (initialTouchCount == 0)
                    {
                        initialTouchCount = Input.touchCount;
                    }
                }
                else
                {
                    initialTouchCount = 0;
                }
            }
        }

        public override void OnBeginDrag(PointerEventData eventData)
        {
            if (SystemInfo.deviceType == DeviceType.Handheld || UnityEditor.EditorApplication.isRemoteConnected)
            {
                if (Input.touchCount >= minimumTouchCount && Input.touchCount == initialTouchCount)
                {
                    eventData.position = MultiTouchPosition;
                    base.OnBeginDrag(eventData);
                }
            }
            else if (SystemInfo.deviceType == DeviceType.Desktop)
            {
                base.OnBeginDrag(eventData);
            }
        }
        public override void OnDrag(PointerEventData eventData)
        {
            if (SystemInfo.deviceType == DeviceType.Handheld || UnityEditor.EditorApplication.isRemoteConnected)
            {
                if (Input.touchCount >= minimumTouchCount && Input.touchCount == initialTouchCount)
                {
                    eventData.position = MultiTouchPosition;
                    base.OnDrag(eventData);
                }
            }
            else if (SystemInfo.deviceType == DeviceType.Desktop)
            {
                base.OnDrag(eventData);
            }          
        }
        public override void OnEndDrag(PointerEventData eventData)
        {
            if (SystemInfo.deviceType == DeviceType.Handheld || UnityEditor.EditorApplication.isRemoteConnected)
            {
                if (Input.touchCount >= minimumTouchCount)
                {
                    eventData.position = MultiTouchPosition;
                    base.OnEndDrag(eventData);
                }
            }
            else if (SystemInfo.deviceType == DeviceType.Desktop)
            {
                base.OnEndDrag(eventData);
            }       
        }
        #endregion
    }
}
0 голосов
/ 23 мая 2019

Попробуйте (не тестировали):

public Vector2 MultiTouchPosition
{
    get
    {
        int nTouches = ((Input.touchCount <= maximumTouchCount) ? Input.touchCount : maximumTouchCount);
        if(nTouches == 1)
        {
             return Input.touches[0].position;
        } 
        else 
        {
             return Vector2.Lerp(Input.touches[0].position, Input.touches[1].position, 0.5f); //middle point between them
        }
    }
 }

Поскольку количество касаний, которое вы хотите обработать, может быть только один или два, лучше обрабатывать каждый случай по-разному.

Я не знаю, почему вы пытались разделить позиции, позиция - это Vector2, и вам нужно вычислить среднюю точку между ними, это можно сделать с помощью Vector2.Lerp (0.5f определяет, что вам нужна средняя точка)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...