Как повернуть группу объектов относительно новой точки?

Программирование на Юнити.

Как повернуть группу объектов относительно новой точки?

Сообщение RikiTikiTak 21 дек 2021, 20:50

Пытаюсь реализовать движение отряда. У каждого члена отряда своя заранее прописанная позиция, ячейка в строю. Как повернуть отряд относительно точки рейкаста. Я нарисовал картинку.

Изображение

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

Если не получится так, то буду пробывать другой метод. Сделать пустой объект, с пустыми дочерными элементами ячейки отряда и пускать его вперёд в точку рейкаста, а координаты дочерных элементов записывать.
RikiTikiTak
UNец
 
Сообщения: 35
Зарегистрирован: 02 сен 2021, 21:08

Re: Как повернуть группу объектов относительно новой точки?

Сообщение waruiyume 21 дек 2021, 22:01

Matrix4x4.TRS- создать систему координат
Matrix4x4.inverse- создать матрицу для переноса в ранее созданную систему
Matrix4x4.MultiplyPoint3x4- перенести в локальную систему
Matrix4x4.Rotate- повернуть систему
Matrix4x4.MultiplyPoint3x4- перенести из локальной в глобальную
Аватара пользователя
waruiyume
Адепт
 
Сообщения: 6143
Зарегистрирован: 30 окт 2010, 05:03
Откуда: Ростов на Дону

Re: Как повернуть группу объектов относительно новой точки?

Сообщение RikiTikiTak 21 дек 2021, 22:54

Огромное вам спасибо. Такими функциями я ещё не пользовался, буду разбираться в том что вы написали . В интернете долго искал по этой теме, но так ничего и не нашёл. Думал, что придётся изобретать велосипед.
RikiTikiTak
UNец
 
Сообщения: 35
Зарегистрирован: 02 сен 2021, 21:08

Re: Как повернуть группу объектов относительно новой точки?

Сообщение RikiTikiTak 25 дек 2021, 00:38

Самому не получилось разобраться. В документации пример с мешем, в интернете тоже не нашёл примеров как работать с координатами. Такое ощущения, что на юнити этого никто не делал раньше.

Вот пример моего кода, как я делаю. Систему координат для ячеек, я использую с игры морской бой. Этот скрипт весит на каждом члене отряда.
Синтаксис:
Используется csharp
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class memberSquad1 : MonoBehaviour
{
    public GameObject sylkaNaGame; // ссылка на объект со скриптами
    public Vector3 cell; //Вариант 1. Ячейка в которой задаю координаты в ручную. Этот вектор складывается с рейкастом.
    public Vector3 yach = new Vector3(); //Вариант 2. Ячейка, в которой координаты получает из списка  
 
}
 


Я нашёл в этой теме www.unity3d.ru/distribution/viewtopic.php?t=17366, ссылку на эту страницу http://habrahabr.ru/post/131931/
Там нашёл тригонометрические формулы,
Синтаксис:
Используется csharp
vec2 rotate(vec2 point, float angle){
           vec2 rotated_point;
           rotated_point.x = point.x * cos(angle) - point.y * sin(angle);
           rotated_point.y = point.x * sin(angle) + point.y * cos(angle);
           return rotated_point;
}


Но у меня они почему то работают не правильно. Вот мой скрипт со списком
Синтаксис:
Используется csharp
using System.Collections;
using System.Collections.Generic;
using UnityEngine;




public class Aspisok : MonoBehaviour
{
    //члены отряда, меняя их местами, меняется позиция в отряде
    public GameObject c1pOb; // это центральный мембер, с координатами (0,0,0)
    public GameObject a1pOb;
    public GameObject e1pOb;
    public GameObject d2pOb;
    public GameObject c3pOb;
   
    public Vector3 castVcentr = new Vector3(); //точка рейкаста, получаем из другого скрипта
 
    public bool vykl = false;
   

    public class yacheyka // создаю ячейки
    {

        public Vector3 izCentraVtochky; // координаты, от центрального
        public float distance; // расстояние, от центрального, посчитанные в другом скрипте

        public yacheyka(Vector3 izCentraVtochky, float distance)
        {
            this.izCentraVtochky = izCentraVtochky;
            this.distance = distance;
        }
    }

    yacheyka a1 = new yacheyka(new Vector3(-80.0f, 0.0f, 0.0f), 80f);
    yacheyka e1 = new yacheyka(new Vector3(80.0f, 0.0f, 0.0f), 80f);
    yacheyka d2 = new yacheyka(new Vector3(40.0f, 0.0f, -40.0f), 56.56854f);
    yacheyka c3 = new yacheyka(new Vector3(0.0f, 0.0f, -80.0f), 80f);

    void Update()
    {

        if (vykl == true)
        {

            Vector3 relativePos = castVcentr - c1pOb.transform.position; //Вектор в точку рейкаста
            var d = Quaternion.LookRotation(relativePos); //Угол поворота в сторону рейкаста
                                                         
            var f = -d.eulerAngles + c1pOb.transform.rotation.eulerAngles; //пытаюсь вычислить, но ничего не получается
                     
            var cosf = Mathf.Cos(f.y);// пытался прописывать в ручную, 90, 45,0 и т.д. закономерности не нашёл
            var sinf = Mathf.Sin(f.y);// вертятся как попало. в 0 градусах выстроились прямо но с инверсией

            //  cos = Mathf.Cos(d.eulerAngles.y);
            // float sin = Mathf.Sin(d.eulerAngles.y);

            c1pOb.GetComponent<memberSquad1>().yach = new Vector3(0f, 0f, 0f);

            float tochkaXcella1 = a1.izCentraVtochky.x * cosf - a1.izCentraVtochky.z * sinf;
            float tochkaZcella1 = a1.izCentraVtochky.x * sinf + a1.izCentraVtochky.z * cosf;
            Vector3 promtochkaa1 = new Vector3(tochkaXcella1, 0f, tochkaZcella1);        
            var a1p = castVcentr - promtochkaa1;
            a1pOb.GetComponent<memberSquad1>().yach = a1p;
           
            float tochkaXcelle1 = e1.izCentraVtochky.x * cosf - e1.izCentraVtochky.z * sinf;
            float tochkaZcelle1 = e1.izCentraVtochky.x * sinf + e1.izCentraVtochky.z * cosf;
            Vector3 promtochkae1 = new Vector3(tochkaXcelle1, 0f, tochkaZcelle1);
            //Vector3 e1p = castVcentr + e1.izCentraVtochky; не знаю как правильно
            Vector3 e1p = castVcentr - promtochkae1;
            e1pOb.GetComponent<memberSquad1>().yach = e1p;

            float tochkaXcelld2 = d2.izCentraVtochky.x * cosf - d2.izCentraVtochky.z * sinf;
            float tochkaZcelld2 = d2.izCentraVtochky.x * sinf + d2.izCentraVtochky.z * cosf;
            Vector3 promtochkad2 = new Vector3(tochkaXcelld2, 0f, tochkaZcelld2);
            // Vector3 d2p = castVcentr + d2.izCentraVtochky;
            Vector3 d2p = castVcentr - promtochkad2;
            d2pOb.GetComponent<memberSquad1>().yach = d2p;

            float tochkaXcellc3 = c3.izCentraVtochky.x * cosf - c3.izCentraVtochky.z * sinf;
            float tochkaZcellc3 = c3.izCentraVtochky.x * sinf + c3.izCentraVtochky.z * cosf;
            Vector3 promtochkac3 = new Vector3(tochkaXcellc3, 0f, tochkaZcellc3);
            // Vector3 e1p = castVcentr + e1.izCentraVtochky;
            Vector3 c3p = castVcentr - promtochkac3;
            c3pOb.GetComponent<memberSquad1>().yach = c3p;

            vykl = false;

        }
    }
}
 


Как внедрить матрицы в мой скрипт? Или что не так с моими формулами?
RikiTikiTak
UNец
 
Сообщения: 35
Зарегистрирован: 02 сен 2021, 21:08

Re: Как повернуть группу объектов относительно новой точки?

Сообщение waruiyume 25 дек 2021, 02:40

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

public class GroupRotate : MonoBehaviour
{
    public Transform piv;
    public float angle = 45;

    public Transform[] targets;
    private Matrix4x4[] tarStartMat;

    private Matrix4x4 toLocalMat;

    void Start()
    {
        toLocalMat = Matrix4x4.TRS(piv.position, Quaternion.identity, Vector3.one).inverse;
       
        tarStartMat = new Matrix4x4[targets.Length];
        for (var i = 0; i < targets.Length; i++)
        {
            tarStartMat[i] = toLocalMat * targets[i].localToWorldMatrix;
        }
    }

    void Update()
    {
        Matrix4x4 resMat = Matrix4x4.TRS(piv.position, Quaternion.Euler(Vector3.up * angle), Vector3.one);

        for (var i = 0; i < targets.Length; i++)
        {
            var m = resMat * tarStartMat[i];
            var t = targets[i];
            t.transform.position = m.GetPosition();
            t.transform.rotation = m.rotation;
        }
    }
}
 


Если вам нужны только позиции, то можно сохранять только локальную позицию, а вместо перемножений матриц использовать Matrix4x4.MultiplyPoint3x4.
Аватара пользователя
waruiyume
Адепт
 
Сообщения: 6143
Зарегистрирован: 30 окт 2010, 05:03
Откуда: Ростов на Дону

Re: Как повернуть группу объектов относительно новой точки?

Сообщение RikiTikiTak 25 дек 2021, 19:37

Спасибо, за то что мне помогаете. В строчке 35 у меня ошибка.
Синтаксис:
Используется csharp
 t.transform.position = m.GetPosition();

"Matrix4x4" не содержит определения "GetPosition", и не удалось найти доступный метод расширения "GetPosition", принимающий тип "Matrix4x4" в качестве первого аргумента (возможно, пропущена директива using или ссылка на сборку).

Остальное пока тестирую.

Я видео снял что у меня не получается.

https://www.youtube.com/watch?v=XLFcrhQOCvo
RikiTikiTak
UNец
 
Сообщения: 35
Зарегистрирован: 02 сен 2021, 21:08

Re: Как повернуть группу объектов относительно новой точки?

Сообщение waruiyume 25 дек 2021, 21:39

Видимо get position в 2021 добавили, вот как он выглядит внутри:
public Vector3 GetPosition() => new Vector3(this.m03, this.m13, this.m23);
Аватара пользователя
waruiyume
Адепт
 
Сообщения: 6143
Зарегистрирован: 30 окт 2010, 05:03
Откуда: Ростов на Дону

Re: Как повернуть группу объектов относительно новой точки?

Сообщение RikiTikiTak 26 дек 2021, 14:43

Я новичок в программировании, изучаю его всего несколько месяцев после работы. Как работает эта конструкция все ещё не понимаю. => это лямба оператор, справку я почитал, но там там тоже надо разбирать каждую строчку кода. Я даже не использую функции, а просто дублирую код.
Если забить в поисковик unity getposition(), то выдаёт примеры из документации, но не в матрице. Вы б не могли дописать в коде как правильно будет.
В вашем скрипте это общий случай. Даже если он заработает, мне его нужно очень сильно переделать, т.к. к нему нужно ещё будет интерфейс сделать, а переборами, отправлением и всем прочим занимаются другие скрипты. Тут я пытаюсь сделать ячейки и поправку для них. Вся информация о ячейках известна заранее, динамически меняться ничего не будет, будет еще один скрипт который будет менять положение юнитов в ячейках.
Матрицы это всё таки сложно. При повороте и перемещении они ведь используют какие-то формулы.
RikiTikiTak
UNец
 
Сообщения: 35
Зарегистрирован: 02 сен 2021, 21:08

Re: Как повернуть группу объектов относительно новой точки?

Сообщение RikiTikiTak 27 дек 2021, 00:41

Я всё же смог сделать через тригонометрию. Оказалось С шарп считает тригонометрию через радианы. Но у меня осталась инверсия когда я двигаю отряд верх вниз.
https://youtu.be/-6V6ZbwUeXk

Может кто нибудь подскажет как это исправить. Это может быть из за того что юнити повороты считает в квартарионах?
RikiTikiTak
UNец
 
Сообщения: 35
Зарегистрирован: 02 сен 2021, 21:08

Re: Как повернуть группу объектов относительно новой точки?

Сообщение RikiTikiTak 27 дек 2021, 19:27

Научился вектора рисовать в консоли и вывел правильные формулы.
Синтаксис:
Используется csharp
 Vector3 relativePos = hit.point - c1pOb.transform.position; // вектор от центрального объекта до точки рейкаста
                    var d = Quaternion.LookRotation(relativePos); //угол поворота
                    Vector3 pryamo = Quaternion.AngleAxis(d.eulerAngles.y, Vector3.up) * Vector3.forward;//вектор направления
                    Vector3 pa1 = Quaternion.AngleAxis(-90, Vector3.up) * pryamo; // вектор направления то точки рейкаста до ячейки, угол в -90 известен, так как ячейки статичны
                    Vector3 a1 = pa1 * 80 + hit.point; // расстояние 80 между ячейками, известно заранее


Эти четыре строчки месяц эксперементально выводить. Работал бы я программистом, ... без соли доедал. :)
RikiTikiTak
UNец
 
Сообщения: 35
Зарегистрирован: 02 сен 2021, 21:08


Вернуться в Скрипты

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

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 10