7 / 6 / 2
Регистрация: 30.07.2013
Сообщений: 94
1

Вращение спрайта вокруг оси Z используя Input.GetTouch

22.04.2020, 21:00. Показов 1193. Ответов 13
Метки нет (Все метки)

Доброго времени суток, Форумчане!

Сейчас работаю над задачей - поворот спрайта вокруг своей оси Z с помощью Input.GetTouch.
Но столкнулся с проблемой, когда пытаюсь вращать спрайт происходят будь то фантомные нажатия и спрайт проворачивается в другую сторону. а иногда не реагирует.
  • Луч не перекрывается.
  • Объектов с таким же тегом нет.

Реализация:
Кликните здесь для просмотра всего текста
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
private void FixedUpdate()
    {
        if (Input.touchCount > 0)
        {
            Touch[] touches = Input.touches;
            for (int i = 0; i < touches.Length; i++)
            {
                Touch touch = Input.GetTouch(i);
 
                Vector3 touchPosition = Camera.main.ScreenToWorldPoint(touch.position);
                Ray ray = Camera.main.ScreenPointToRay(Input.GetTouch(i).position);
                RaycastHit hit;
                if (Physics.Raycast(ray, out hit, Mathf.Infinity))
                {
                    if (hit.collider.gameObject.tag == "Platform")
                    {
                        switch (touch.phase)
                        {
                            case TouchPhase.Began:
                                startDirection = touchPosition - transform.position;
                                break;
 
                            case TouchPhase.Moved:
                                var currentDirection = touchPosition - transform.position;
                                float angle = Vector2.SignedAngle(startDirection, currentDirection);
                                var euler = transform.eulerAngles;
                                euler.z += angle;
                                transform.eulerAngles = euler;
                                startDirection = currentDirection;
                                break;
                        }
                    }
                }
            }
        }
    }
0

Помощь в написании контрольных, курсовых и дипломных работ здесь.

Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
22.04.2020, 21:00
Ответы с готовыми решениями:

Вращение объекта вокруг своей оси
Здравствуйте я полный новичок в unity3d, недавно столкнулся с такой проблемой, буду рад если...

Вращение объекта вокруг определённой оси
Приветствую, форумчане. Ситуация: есть самолёт с подвижными органами управления (элероны, руль...

Input.GetTouch
Принцип игры таков, что необходимо забросить мяч в своеобразную корзину. Бросок делается при помощи...

Вращение планеты вокруг солнца, и вокруг своей оси
У меня есть Солнце, которое находиться в координатах(0.0.0), и нужно вращать планеты, как по...

13
66 / 46 / 20
Регистрация: 09.10.2013
Сообщений: 156
22.04.2020, 21:11 2
В сам код пока особо не вникал, но немного смутила самая первая строчка.
Вы уверены, что FixedUpdate() является подходящим местом для обработки ввода?

P.S. 1, 2, 3
0
7 / 6 / 2
Регистрация: 30.07.2013
Сообщений: 94
22.04.2020, 21:20  [ТС] 3
Цитата Сообщение от squakoon Посмотреть сообщение
Вы уверены, что FixedUpdate() является подходящим местом для обработки ввода?
Кнопок нет, вращаю непосредственно при контакте со спрайтом по направлению движения свайпа..
0
66 / 46 / 20
Регистрация: 09.10.2013
Сообщений: 156
22.04.2020, 21:22 4
Цитата Сообщение от Mr Destructor Посмотреть сообщение
Кнопок нет, вращаю непосредственно при контакте со спрайтом по направлению движения свайпа..
О кнопках речь не шла. Любой input — это input. Независимо от того, курсором на экране во что-то тыкать, или пальцем в тач-дисплей.
Поправьте, если я неверно истолковал ваше сообщение.
0
7 / 6 / 2
Регистрация: 30.07.2013
Сообщений: 94
22.04.2020, 21:38  [ТС] 5
Цитата Сообщение от squakoon Посмотреть сообщение
Поправьте, если я неверно истолковал ваше сообщение.
Скорее я не правильно понял, с API - Touch работаю впервые до недавнего времени, решил реализовывать в FixedUpdate() для плавного движения. проект не затратный по ресурсам, решил раскошелится, да и советуют делать в Update().
С UnityEngine.EventSystems пока не разбирался.. если вы о IPointerDownHandler и все в этом роде)
0
66 / 46 / 20
Регистрация: 09.10.2013
Сообщений: 156
22.04.2020, 21:47 6
Mr Destructor, пока не совсем точно улавливаю связь в ваших словах.
В приведённом вами коде обработка касаний реализована в методе FixedUpdate(). Насколько мне известно из личного опыта и информации в сети (как пример, те три ссылки, представленные в моём первом сообщении), такие вещи необходимо реализовывать исключительно в Update(). Если у вас ещё не так, попробуйте описанный мной подход и протестируйте реальное приложение на наличие прежних проблем.
0
7 / 6 / 2
Регистрация: 30.07.2013
Сообщений: 94
22.04.2020, 22:21  [ТС] 7
Цитата Сообщение от squakoon Посмотреть сообщение
такие вещи необходимо реализовывать исключительно в Update()
Запихнул в Update() (из наблюдений - работает одинаково), решил проблему фантомных нажатий с помощью проверки в начале :
C#
1
if (Input.touchCount < 2)
вместо:
C#
1
if (Input.touchCount > 0)
так же исправил дважды объявленный Touch.

Кликните здесь для просмотра всего текста
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
private void Update()
    {
        if (Input.touchCount < 2)
        {
            Touch[] touches = Input.touches;
            for (int i = 0; i < touches.Length; i++)
            {
                Vector3 touchPosition = Camera.main.ScreenToWorldPoint(touches[i].position);
                Ray ray = Camera.main.ScreenPointToRay(Input.GetTouch(i).position);
                RaycastHit hit;
                if (Physics.Raycast(ray, out hit, Mathf.Infinity))
                {
                    if (hit.collider.gameObject.tag == "Platform")
                    {
                        switch (touches[i].phase)
                        {
                            case TouchPhase.Began:
                                startDirection = touchPosition - transform.position;
                                break;
 
                            case TouchPhase.Moved:
                                var currentDirection = touchPosition - transform.position;
                                float angle = Vector2.SignedAngle(startDirection, currentDirection);
                                var euler = transform.eulerAngles;
                                euler.z += angle;
                                transform.eulerAngles = euler;
                                startDirection = currentDirection;
                                break;
                        }
                    }
                }
            }
        }
    }


но осталась проблема с тем что иногда не реагирует на свайп..

Добавлено через 14 минут
так же не могу понять почему startDirection иногда обновляется в рандомную позицию, после того как я вновь пытаюсь повернуть спрайт.
0
66 / 46 / 20
Регистрация: 09.10.2013
Сообщений: 156
22.04.2020, 23:39 8
Я не тестировал свой код и вовсе не уверен что он корректно работающий, но возможно в вашей ситуации будет полезно как минимум проанализировать альтернативный вариант решения задачи.
Кликните здесь для просмотра всего текста
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
    private const string PlatformTag = "Platform";
    private const int NullTouchId = -1; // or something else value
    private int _touchID;
    
    private void Update()
    {
        Camera camera = Camera.main;
        
        foreach (var touch in Input.touches)
        {
            if (_touchID != NullTouchId && _touchID != touch.fingerId)
            {
                continue;
            }
 
            Ray ray = camera.ScreenPointToRay(touch.position);
            if (Physics.Raycast(ray, out RaycastHit hit, Mathf.Infinity) && hit.collider.CompareTag(PlatformTag))
            {
                switch (touch.phase)
                {
                    case TouchPhase.Began:
                    {
                        _touchID = touch.fingerId;
                        break;
                    }
                    case TouchPhase.Ended:
                    case TouchPhase.Canceled:
                    {
                        _touchID = NullTouchId;
                        break;
                    }
                    default:
                    {
                        Vector2 anchor = camera.WorldToScreenPoint(transform.position);
                        float angle = Vector2.SignedAngle(touch.position + touch.deltaPosition - anchor, touch.position - anchor);
                        transform.eulerAngles += Vector3.forward * angle;
                        break;
                    }
                }
 
                break;
            }
 
            _touchID = NullTouchId;
        }
    }
1
7 / 6 / 2
Регистрация: 30.07.2013
Сообщений: 94
22.04.2020, 23:51  [ТС] 9
Цитата Сообщение от squakoon Посмотреть сообщение
корректно работающий
Работает отлично, спасибо большое, единственное напутали со знаками и вращение было против свайпа)
нужно передать с минусом:
C#
1
transform.eulerAngles -= Vector3.forward * angle;
Еще есть пожалуй последний вопрос, который не могу решить, как избавится от ускорения вращения в центре экрана, может
transform.eulerAngles преобразовать в Quaternion?
0
66 / 46 / 20
Регистрация: 09.10.2013
Сообщений: 156
22.04.2020, 23:55 10
Цитата Сообщение от Mr Destructor Посмотреть сообщение
как избавится от ускорения вращения в центре экрана
Не совсем понял вопрос. Имеется в виду в принципе замедлить скорость вращения, или убавить резкость если касание проходит вблизи пивота спрайта?
Переформулируйте, пожалуйста, ваш вопрос.
0
7 / 6 / 2
Регистрация: 30.07.2013
Сообщений: 94
23.04.2020, 00:00  [ТС] 11
Цитата Сообщение от squakoon Посмотреть сообщение
убавить резкость если касание проходит вблизи пивота спрайта?
Убрать резкость (у меня спрайт находится в центре экрана), для примера если вращать спрайт от угла и проходить через центр он меняет положение в минус(мне так кажется) и переворачивается, или делает оборот я так и не понял.
0
66 / 46 / 20
Регистрация: 09.10.2013
Сообщений: 156
23.04.2020, 00:16 12
В данном случае можно придумать какие-то костыли в виде смещения anchor (из приведённого мной кода) так, чтобы между точкой касания и пивотом спрайта всегда соблюдалась некая минимальная дистанция. Например, построить треугольник по пивоту спрайта и точкам касания текущего и предыдущего кадров, а затем измерять длину медианы проведённой из точки соответствующей пивоту спрайта и в случае чего уводить эту вершину вдоль продолжения исходной медианы за пределами треугольника.
Но насколько это будет визуально корректно отображаться — не понятно.
К сожалению, предложить более оптимальный вариант или по-человечески описать свою концепцию сейчас не могу.
0
7 / 6 / 2
Регистрация: 30.07.2013
Сообщений: 94
23.04.2020, 15:18  [ТС] 13
Цитата Сообщение от squakoon Посмотреть сообщение
В данном случае можно придумать какие-то костыли
Они самые.

не оптимизировано правда, но работает..
Кликните здесь для просмотра всего текста
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
void Start(){
        CenterScreen = new Vector2(Screen.width / 2,Screen.height / 2);
        ForPercentage = Mathf.Sqrt (Screen.width * Screen.width + Screen.height * Screen.height);
    }
 
    private void Update()
    {
        Camera camera = Camera.main;
 
        foreach (var touch in Input.touches)
        {
            if (_touchID != NullTouchId && _touchID != touch.fingerId)
            {
                continue;
            }
 
            Ray ray = camera.ScreenPointToRay(touch.position);
            if (Physics.Raycast(ray, out RaycastHit hit, Mathf.Infinity) && hit.collider.CompareTag(PlatformTag))
            {
                switch (touch.phase)
                {
                    case TouchPhase.Began:
                        {
                            _touchID = touch.fingerId;
                            SavePosition = new Vector2(touch.position.x, touch.position.y);
                            break;
                        }
                    case TouchPhase.Ended:
                    case TouchPhase.Canceled:
                        {
                            _touchID = NullTouchId;
                            SavePosition = new Vector2(touch.position.x, touch.position.y);
                            break;
                        }
                    default:
                        {
                            CurrentPosition = new Vector2(touch.position.x, touch.position.y);
                            Direction = SavePosition - CurrentPosition;
                            if (Direction.x < 0)
                                Direction = new Vector2(-Direction.x, Direction.y);
                            if (Direction.y < 0)
                                Direction = new Vector2(Direction.x, -Direction.y);
                            Direction = new Vector2(Mathf.Sqrt(Direction.x * Direction.x + Direction.y * Direction.y) * 100 / (ForPercentage * ConvertDelta), 0);
 
                            if (CurrentPosition.y > CenterScreen.y)
                            {
                                if (CurrentPosition.x < SavePosition.x)
                                    Platform.Rotate(0, 0, Direction.x);
                                else
                                    Platform.Rotate(0, 0, -Direction.x);
                            }
                            if (CurrentPosition.y < CenterScreen.y)
                            {
                                if (CurrentPosition.x > SavePosition.x)
                                    Platform.Rotate(0, 0, Direction.x);
                                else
                                    Platform.Rotate(0, 0, -Direction.x);
                            }
                            if (CurrentPosition.x > CenterScreen.x)
                            {
                                if (CurrentPosition.y > SavePosition.y)
                                    Platform.Rotate(0, 0, Direction.x);
                                else
                                    Platform.Rotate(0, 0, -Direction.x);
                            }
                            if (CurrentPosition.x < CenterScreen.x)
                            {
                                if (CurrentPosition.y < SavePosition.y)
                                    Platform.Rotate(0, 0, Direction.x);
                                else
                                    Platform.Rotate(0, 0, -Direction.x);
                            }
                            SavePosition = new Vector2(touch.position.x, touch.position.y);
                            break;
                        }
                }
 
                break;
            }
 
            _touchID = NullTouchId;
        }
    }


Кликните здесь для просмотра всего текста
C#
1
public float ConvertDelta = 1.3f;


Добавлено через 3 минуты
Получается не плавное вращение, может использовать Quaternion.lerp?
0
66 / 46 / 20
Регистрация: 09.10.2013
Сообщений: 156
23.04.2020, 19:33 14
Цитата Сообщение от Mr Destructor Посмотреть сообщение
Получается не плавное вращение, может использовать Quaternion.lerp?
Можете ещё посмотреть в сторону Vector3.SmoothDamp()
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
23.04.2020, 19:33

Вращение примитива вокруг оси z
Здравствуйте! Необходимо повернуть квадрат вокруг оси z на заданный угол, по нажатию кнопки. (язык...

Вращение прямоугольника вокруг оси
Программа должна вращать прямоугольник с заданными параметрами длины и ширины, вокруг оси. Общий...

Вращение линии вокруг оси
Ребята, помогите пожалуйста! Как сделать в матлабе график вращения линии вокруг оси? Вот есть...

Вращение букв вокруг оси
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data;...

Вращение колеса вокруг своей оси
Помогите. Я уже запарилась. В общем, мне нужно что бы колесо со спицами двигалось по осе X и...

Pascal Graph. Вращение вокруг оси
Необходимо задать единую ось, вокруг которой вращаются круги program lab8; uses GraphABC; ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
14
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.