UI указатель 3D пространства[Решено][с костылём 100%]

Форум для самых маленьких, а так же тех, кому недосуг читать справку самостоятельно.

UI указатель 3D пространства[Решено][с костылём 100%]

Сообщение I-Dgt 17 июл 2018, 15:25

Понадобилось сделать на экранный маркер(указатель), так как я в гугол не смог написал скрипт, который перемещает 3D объект перед камерой. Скрипт я переписал под UI, а оригинал для 3D объекта потерян, так что далее будет лишь реставрация(скрипт внизу).
Изображение
Скрытый текст:
Изображение
Изображение

Скрипт который использую сейчас:
Синтаксис:
Используется csharp
using UnityEngine;

public class Marker : MonoBehaviour {
        public Transform target;
        public RectTransform marker;
        public RectTransform arrow;
        Vector3 _t;
        public Vector2 _d;
        public Vector2 _b;
        public float _w;
        public float _h;
        public float soot;
        Quaternion arrowZero;
        public bool X;
        public bool Y;
        void Start () {
                arrowZero = arrow.rotation;
        }
        void LateUpdate () {
                _t = transform.InverseTransformVector (target.position - transform.position);
                if (!Mathf.Approximately(_t.z, 0)) {
                        _w = Screen.width / 2;
                        _h = Screen.height / 2;
                        _w -= 50;
                        _h -= 50;
                        _d.x = _t.x;
                        _d.y = _t.y;
                        _d /= Mathf.Abs (_t.z);
                        _d.x = _d.x * soot;
                        _d.y = _d.y * soot + 50;
                        _b.x = Mathf.Clamp (_d.x, - _w, _w);
                        _b.y = Mathf.Clamp (_d.y, - _h, _h);
                }
                marker.anchoredPosition = _b;
                X = !Mathf.Approximately (_d.x, _b.x);
                Y = !Mathf.Approximately (_d.y, _b.y);
                if (X || Y) {
                        arrow.rotation = Quaternion.LookRotation (Vector3.forward, - _d);
                } else {
                        arrow.rotation = arrowZero;
                }
        }
}

А теперь проблемы моей реализации:
1)Если развернуться на 180, то маркер будет показывать в пустоту(эта проблема как в 1ой версии скрипта, так и во 2ой).
Скрытый текст:
Изображение

2)В скрипте для UI, есть некое значение soot(возможно ругательная аббревиатура, я уже не помню), методом научного тыка было получено значение 666 для разрешения экрана 1024x768. Но при этом в оригинальном скрипте такого не было, при реставрации такого результата не удалось достичь, там так же 666.
Скрытый текст:
Изображение

Скрытый текст:
Изображение
Изображение

Реставрация скрипта:
Синтаксис:
Используется csharp
using UnityEngine;

public class Marker3D : MonoBehaviour {
        public Transform target;
        public Transform marker;
        Vector3 _t;
        public Vector3 _d;
        public Vector3 _b;
        public float _w;
        public float _h;
        void LateUpdate () {
                _t = transform.InverseTransformVector (target.position - transform.position);
                if (!Mathf.Approximately(_t.z, 0)) {
                        _w = Screen.width / 2;
                        _h = Screen.height / 2;
                        _w -= 50;
                        _h -= 50;
                        _w /= 666;
                        _h /= 666;
                        _d.x = _t.x;
                        _d.y = _t.y;
                        _d.z = 1;
                        _d /= Mathf.Abs (_t.z);
                        _d.x = _d.x;
                        _d.y = _d.y + 0.075f;
                        _b.x = Mathf.Clamp (_d.x, - _w, _w);
                        _b.y = Mathf.Clamp (_d.y, - _h, _h);
                        _b.z = 1;
                }
                marker.localPosition = _b;
        }
}

Если кто знает как гуглить или другие решение(а лучше и то и то), дайте знать.
Последний раз редактировалось I-Dgt 17 июл 2018, 23:56, всего редактировалось 2 раз(а).
Аватара пользователя
I-Dgt
UNIт
 
Сообщения: 142
Зарегистрирован: 29 дек 2013, 18:20

Re: UI указатель 3D пространства

Сообщение Cr0c 17 июл 2018, 15:51

Там же можно просто переводить мировые в экранные и ставить туда маркер.
Аватара пользователя
Cr0c
Адепт
 
Сообщения: 3035
Зарегистрирован: 19 июн 2015, 13:50
Skype: cr0c81

Re: UI указатель 3D пространства

Сообщение I-Dgt 17 июл 2018, 16:19

Cr0c писал(а):Там же можно просто переводить мировые в экранные и ставить туда маркер.

Ещё бы понимать как это и чем отличается от моего метода.
Аватара пользователя
I-Dgt
UNIт
 
Сообщения: 142
Зарегистрирован: 29 дек 2013, 18:20

Re: UI указатель 3D пространства

Сообщение Cr0c 17 июл 2018, 16:26

Синтаксис:
Используется csharp
Vector3 guiPos = Camera.main.WorldToScreenPoint(mark.position);
markImage.position = guiPos;
 

mark - трансформ метки в сцене
markImage - трансформ картинки метки на канвасе
Аватара пользователя
Cr0c
Адепт
 
Сообщения: 3035
Зарегистрирован: 19 июн 2015, 13:50
Skype: cr0c81

Re: UI указатель 3D пространства

Сообщение I-Dgt 17 июл 2018, 16:30

Cr0c писал(а):
Синтаксис:
Используется csharp
Vector3 guiPos = Camera.main.WorldToScreenPoint(mark.position);
markImage.position = guiPos;
 

mark - трансформ метки в сцене
markImage - трансформ картинки метки на канвасе

Делал так, маркер гдет в углу, сейчас попробую пошаманить(думал раз не работает поищу другой метод, ну раз посоветовал, буду проводить эксперименты).
Аватара пользователя
I-Dgt
UNIт
 
Сообщения: 142
Зарегистрирован: 29 дек 2013, 18:20

Re: UI указатель 3D пространства

Сообщение I-Dgt 17 июл 2018, 16:33

I-Dgt писал(а):Делал так, маркер гдет в углу, сейчас попробую пошаманить(думал раз не работает поищу другой метод, ну раз посоветовал, буду проводить эксперименты).

Нашёл, marker.anchoredPosition = _b; исправил на marker.position = _b;
Аватара пользователя
I-Dgt
UNIт
 
Сообщения: 142
Зарегистрирован: 29 дек 2013, 18:20

Re: UI указатель 3D пространства[50%Решено]

Сообщение I-Dgt 17 июл 2018, 16:35

Всё равно если повернутся на 180, то маркер в пустоту показывает.
Аватара пользователя
I-Dgt
UNIт
 
Сообщения: 142
Зарегистрирован: 29 дек 2013, 18:20

Re: UI указатель 3D пространства[50%Решено]

Сообщение Cr0c 17 июл 2018, 18:03

Так выключай маркер, когда он по XZ угол к forward имеет больше fov'а камеры
Аватара пользователя
Cr0c
Адепт
 
Сообщения: 3035
Зарегистрирован: 19 июн 2015, 13:50
Skype: cr0c81

Re: UI указатель 3D пространства[50%Решено]

Сообщение 1max1 17 июл 2018, 18:25

Так выключай маркер, когда он по XZ угол к forward имеет больше fov'а камеры

гениально))
Всё равно если повернутся на 180, то маркер в пустоту показывает.

Придется делать костыли, по другому никак)
Аватара пользователя
1max1
Адепт
 
Сообщения: 5505
Зарегистрирован: 28 июн 2017, 10:51

Re: UI указатель 3D пространства[50%Решено]

Сообщение I-Dgt 17 июл 2018, 19:02

1max1 писал(а):Придется делать костыли, по другому никак)

К этому же пришёл, сделаю выложу.
Аватара пользователя
I-Dgt
UNIт
 
Сообщения: 142
Зарегистрирован: 29 дек 2013, 18:20

Re: UI указатель 3D пространства[100%Решено]

Сообщение I-Dgt 17 июл 2018, 23:54

Cr0c писал(а):

1max1 писал(а):

Спс за помощь, хоть я и приходил к тем же умозаключениям, вы устраняли колебания во мне.
(3A4OT)
Вот код если кому понадобится:
Синтаксис:
Используется csharp
using UnityEngine;

public class Marker : MonoBehaviour {
        public Transform target;
        public RectTransform marker;
        public RectTransform arrow;
        Vector3 _t;
        Vector2 _d;
        Vector2 _b;
        float _w;
        float _h;
        Quaternion arrowZero;
        bool X;
        bool Y;
        public Camera cam;
        float angX;
        float angY;
        public float _size = 50;
        void Start () {
                arrowZero = arrow.rotation;
        }
        void LateUpdate () {
                _t = cam.WorldToScreenPoint (target.position);
                _w = Screen.width / 2;
                _h = Screen.height / 2;
                _t.x -= _w;
                _t.y -= _h;
                _w -= _size / 2;
                _h -= _size / 2;
                _b = _t;
                _d.x = _t.y;
                _d.y = _t.x;
                angX = Vector2.Angle(Vector2.right, _t);
                angY = Vector2.Angle(Vector2.right, _d);
                angX -= 90;
                angY -= 90;
                Vector2 _v = _b;
                _v.y += _size;
                if (_t.z > 0) {
                        bool _ooo = ((_b.x > _w) | (_b.y > _h));
                        bool _too = ((_b.x < -_w) | (_b.y < -_h));
                        bool _foo = (_ooo | _too);
                        if (_foo) {
                                if (Mathf.Abs (angX) > Mathf.Abs (angY)) {
                                        if (Mathf.Sign (angX) > 0) {
                                                _v.x = -_w;
                                        } else {
                                                _v.x = _w;
                                        }
                                        _v.y = Mathf.Clamp(Mathf.Tan (angY * Mathf.Deg2Rad) * - _w, -_h, _h);
                                } else {
                                        if (Mathf.Sign (angY) > 0) {
                                                _v.y = -_h;
                                        } else {
                                                _v.y = _h;
                                        }
                                        _v.x = Mathf.Clamp(Mathf.Tan (angX * Mathf.Deg2Rad) * - _h, -_w, _w);
                                }
                        }
                } else {
                        if (Mathf.Abs (angX) > Mathf.Abs (angY)) {
                                if (Mathf.Sign (angX) > 0) {
                                        _v.x = _w;
                                } else {
                                        _v.x = -_w;
                                }
                                _v.y = Mathf.Clamp(Mathf.Tan (angY * Mathf.Deg2Rad) * _w, -_h, _h);
                        } else {
                                if (Mathf.Sign (angY) > 0) {
                                        _v.y = _h;
                                } else {
                                        _v.y = -_h;
                                }
                                _v.x = Mathf.Clamp(Mathf.Tan (angX * Mathf.Deg2Rad) * _h, -_w, _w);
                        }
                }
                _b = _v;
                marker.anchoredPosition = _b;
                X = !Mathf.Approximately (_t.x, _b.x);
                Y = !Mathf.Approximately (_t.y + _size, _b.y);
                if (X || Y) {
                        if (_t.z > 0) {
                                arrow.rotation = Quaternion.LookRotation (Vector3.forward, -_t);
                        } else {
                                arrow.rotation = Quaternion.LookRotation (Vector3.forward, _t);
                        }
                } else {
                        arrow.rotation = arrowZero;
                }
        }
}
Аватара пользователя
I-Dgt
UNIт
 
Сообщения: 142
Зарегистрирован: 29 дек 2013, 18:20

Re: UI указатель 3D пространства[Решено][с костылём 100%]

Сообщение Cr0c 18 июл 2018, 21:17

Вообще-то тут намного меньше кода
Синтаксис:
Используется csharp
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MouseControl : MonoBehaviour {

    public float mouseSensitive = 2f;
    public Transform controlled;

    public Transform target;
    public Transform uiMarker;
    private Camera cam;

        void Start () {
        cam = Camera.main;
        }
       
        void Update () {
        if (controlled != null && Input.GetMouseButton(0))
        {
            float mx = Input.GetAxis("Mouse X") * mouseSensitive;
            float my = Input.GetAxis("Mouse Y") * mouseSensitive;
            controlled.Rotate(Vector3.up, mx, Space.World);
            controlled.Rotate(Vector3.left, my, Space.Self);
        }
        if (target != null && uiMarker != null)
        {
            Vector3 targetXZpos = target.position;
            targetXZpos.y = controlled.position.y;
            float angle = Vector3.Angle(controlled.forward, targetXZpos - controlled.position);
            if (angle <= cam.fieldOfView)
            {
                if (!uiMarker.gameObject.activeSelf)
                    uiMarker.gameObject.SetActive(true);
                Vector3 uiPos = cam.WorldToScreenPoint(target.position);
                uiMarker.position = uiPos;
            }
            else
            {
                if (uiMarker.gameObject.activeSelf)
                    uiMarker.gameObject.SetActive(false);
            }
        }
    }
}
 
Аватара пользователя
Cr0c
Адепт
 
Сообщения: 3035
Зарегистрирован: 19 июн 2015, 13:50
Skype: cr0c81


Вернуться в Почемучка

Кто сейчас на конференции

Сейчас этот форум просматривают: Yandex [Bot] и гости: 28