Как определить силу которая воздействует на Rigidbody

Физика в Unity

Как определить силу которая воздействует на Rigidbody

Сообщение IDoNotExist 22 июн 2012, 12:05

По идее все должно быть легко и просто "Сила = Масса * Ускорение". То есть, по идее чтобы нам мгновенно остановить движущееся Rigigdbody достаточно этого:

Синтаксис:
Используется csharp
public bool unlockForce = false;

void FixedUpdate(){
     if(unlockForce)
          rigidbody.AddForce( -rigidbody.velocity*rigidbody.mass, ForceMode.Impulse);
}
 


Да вот только Rigidbody продолжает двигаться. И чтобы уже полностью остановить Rigidbody на которое действует допустим только сила гравитации. Надо добавить еще и:

Синтаксис:
Используется csharp
public bool unlockForce = false;

void FixedUpdate(){
     if(unlockForce)
          rigidbody.AddForce( 0, 9.81f, 0 , ForceMode.Force);
}
 


Как я понял Rigidbody в текущем физическом шаге не до конца рассчитывает ускорение на основе всех приложенных к нему сил. Или я чегото не понимаю?

Вопрос в том, как мне рассчитать правильное ускорение с учетом всех действующих сил на основе ускорение ( или чего нибудь другого) если мы наверняка не знаем какие силы действуют на него, чтобы можно было написать допустим вот так:

Синтаксис:
Используется csharp
public bool unlockForce = false;

void FixedUpdate(){
     if(unlockForce)
           rigidbody.AddForce( -trueVelocity*rigidbody.mass, ForceMode.Impulse);
}
 


И Rigidbody остановилось бы полностью.
Последний раз редактировалось IDoNotExist 22 июн 2012, 18:24, всего редактировалось 1 раз.
Аватара пользователя
IDoNotExist
Адепт
 
Сообщения: 1432
Зарегистрирован: 23 мар 2011, 09:18
Skype: iamnoexist

Re: Как определить силу которая воздействует на Rigidbody

Сообщение bojlahg 22 июн 2012, 16:22

чтобы мгновенно остановить rigidbody можно сделать проще:
rigidbody.velocity = Vector3.zero;
Мои проекты: MahJah Star Factory Cop Car Swash! Spline Editor
Аватара пользователя
bojlahg
UNIверсал
 
Сообщения: 392
Зарегистрирован: 13 авг 2011, 10:57
Откуда: Сатка
Skype: bojlahg
  • Сайт

Re: Как определить силу которая воздействует на Rigidbody

Сообщение IDoNotExist 22 июн 2012, 18:33

bojlahg писал(а):чтобы мгновенно остановить rigidbody можно сделать проще:
rigidbody.velocity = Vector3.zero;

Да это понятно, смысл вопроса был в том чтобы остановить его именно силой. У меня есть объекты которые воздействуют на Rigidbody не в центре масс а в определенных точках (т.е. с помощью AddForceAtPosition()), модифицировать ускорение в этих точках можно только с помощью силы вот я и пытаюсь понять как мне правильно рассчитать эту силу.
Аватара пользователя
IDoNotExist
Адепт
 
Сообщения: 1432
Зарегистрирован: 23 мар 2011, 09:18
Skype: iamnoexist

Re: Как определить силу которая воздействует на Rigidbody

Сообщение bojlahg 22 июн 2012, 19:32

Пробовал на простом примере, тело останавливается. Но если приложить к нему в тот же момент дополнительную силу то немного движется.
(Например в примере зажать G+Space+Left). Но тут вроде логика не нарушена.
Синтаксис:
Используется csharp
public class PhysTest : MonoBehaviour
{
        private void FixedUpdate()
        {
                if(Input.GetKey(KeyCode.UpArrow))
                {
                        rigidbody.AddForce(Vector3.up * 20);
                }
                if(Input.GetKey(KeyCode.DownArrow))
                {
                        rigidbody.AddForce(Vector3.down * 20);
                }
                if(Input.GetKey(KeyCode.LeftArrow))
                {
                        rigidbody.AddForce(Vector3.left * 20);
                }
                if(Input.GetKey(KeyCode.RightArrow))
                {
                        rigidbody.AddForce(Vector3.right * 20);
                }
                if(Input.GetKey(KeyCode.Space))
                {
                        rigidbody.AddForce(-rigidbody.velocity * rigidbody.mass, ForceMode.Impulse);
                }
                if(Input.GetKey(KeyCode.G))
                {
                        rigidbody.AddForce(-Physics.gravity, ForceMode.Acceleration);
                }
                if(Input.GetKey(KeyCode.LeftArrow) &&
                        Input.GetKey(KeyCode.Space) &&
                        Input.GetKey(KeyCode.G))
                {
                        Debug.Log("Break");
                }
        }
}
 
Мои проекты: MahJah Star Factory Cop Car Swash! Spline Editor
Аватара пользователя
bojlahg
UNIверсал
 
Сообщения: 392
Зарегистрирован: 13 авг 2011, 10:57
Откуда: Сатка
Skype: bojlahg
  • Сайт

Re: Как определить силу которая воздействует на Rigidbody

Сообщение IDoNotExist 23 июн 2012, 17:32

bojlahg писал(а):Пробовал на простом примере, тело останавливается. Но если приложить к нему в тот же момент дополнительную силу то немного движется.
(Например в примере зажать G+Space+Left). Но тут вроде логика не нарушена.
Синтаксис:
Используется csharp
public class PhysTest : MonoBehaviour
{
        private void FixedUpdate()
        {
                if(Input.GetKey(KeyCode.UpArrow))
                {
                        rigidbody.AddForce(Vector3.up * 20);
                }
                if(Input.GetKey(KeyCode.DownArrow))
                {
                        rigidbody.AddForce(Vector3.down * 20);
                }
                if(Input.GetKey(KeyCode.LeftArrow))
                {
                        rigidbody.AddForce(Vector3.left * 20);
                }
                if(Input.GetKey(KeyCode.RightArrow))
                {
                        rigidbody.AddForce(Vector3.right * 20);
                }
                if(Input.GetKey(KeyCode.Space))
                {
                        rigidbody.AddForce(-rigidbody.velocity * rigidbody.mass, ForceMode.Impulse);
                }
                if(Input.GetKey(KeyCode.G))
                {
                        rigidbody.AddForce(-Physics.gravity, ForceMode.Acceleration);
                }
                if(Input.GetKey(KeyCode.LeftArrow) &&
                        Input.GetKey(KeyCode.Space) &&
                        Input.GetKey(KeyCode.G))
                {
                        Debug.Log("Break");
                }
        }
}
 


Ну все правильно об этом я и говорю, немного движется оно потому что на него действует дополнительная сила (например rigidbody.AddForce(Vector3.left * 20);).
После выполнения FixedUpdate() движок учитывает все силы и применяет их к Rigidbody, но так как сила Vector3.left * 20 еще не дала нам ускорения, значит сила rigidbody.AddForce(-rigidbody.velocity * rigidbody.mass, ForceMode.Impulse); будет нейтрализовывать ускорение не в полной мере, и в следующем кадре мы увидим движение.

В этом случае остается только каким нибудь образом вычислить силы которые будут действовать на Rigidbody, и на основе них рассчитывать новое ускорение, вот я и спрашиваю как это можно сделать.
Аватара пользователя
IDoNotExist
Адепт
 
Сообщения: 1432
Зарегистрирован: 23 мар 2011, 09:18
Skype: iamnoexist

Re: Как определить силу которая воздействует на Rigidbody

Сообщение _Disa_ 25 июн 2012, 14:05

Ну так мб если F=m/a, а a=d^2r/dt^2 (вторая производна по времени от радиус-вектора, извините за много букв a подряд), через разностную схему будет так:
V1 = (r11-r12)/(deltaTime), V2 = (r21-r22)/deltaTime, r11-r12, r21-r22 - соответствующие вектора перемещения
a = (V1-V2)/deltaTime, где V1 скорость в текущем кадре, V2 в прошлом

Не уверен, что не велосипед. Но первое, что пришло в голову и как говориться "не недооценивайте силу брутфорса" :)
ArShift
_Disa_
UNIт
 
Сообщения: 97
Зарегистрирован: 07 мар 2012, 09:07
Откуда: Нерезиновая
Skype: islamov_denis
  • Сайт

Re: Как определить силу которая воздействует на Rigidbody

Сообщение IDoNotExist 26 июн 2012, 10:38

_Disa_ писал(а):a = (V1-V2)/deltaTime, где V1 скорость в текущем кадре, V2 в прошлом

А как быть если V1 = V2?
Аватара пользователя
IDoNotExist
Адепт
 
Сообщения: 1432
Зарегистрирован: 23 мар 2011, 09:18
Skype: iamnoexist

Re: Как определить силу которая воздействует на Rigidbody

Сообщение IDoNotExist 26 июн 2012, 11:01

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

Из этой ситуации конечно есть выходы, но в виде всяческих извращений, например можно складировать где нибудь все силы с помощью которыx будем манипулировать данным телом, а потом учитывать их при воздействии (а-ля менеджер сил). Можно как выше написали использовать несколько кадров чтобы рассчитать реальное ускорение. Я предполагаю что где то в недрах PhysX это все уже есть, просто к этому нет доступа из [unity 3D].
Аватара пользователя
IDoNotExist
Адепт
 
Сообщения: 1432
Зарегистрирован: 23 мар 2011, 09:18
Skype: iamnoexist

Re: Как определить силу которая воздействует на Rigidbody

Сообщение _Disa_ 26 июн 2012, 19:20

По идее - нет ускорения, нет силы. Но импульс, конечно, никто не отменял . Он будет только в случае столкновений с объектом (т.к. при отсутствии внешних сил сумма импульсов нулевая) :) По уму вероятно, нужно при столкновении учитывать "будущее" ускорение (и при столкновении брать его с отрицательным знаком).

Вообще если в системе все тела либо свободны, либо жестко связаны - то можно все описать 2мя диффурами (з-н сохранения энергии и импульса) + начальные (или граничные в зависимости от задачи) условия для нахождения констант в решениях. Если связи не жесткие - то еще + з-н Гука в дифф. форме (ну это если тела упругие и все деформации конечные и упругие).
Для партиклей, по идее нужно по другому считать - в зависимости что они такое (жидкость, газ).

Ну насколько я знаю в физиксе все модели не совсем честные, а весьма упрощенные, для ускорения обсчетов (ну мол выглядит как настоящие, ну и ладно).
ArShift
_Disa_
UNIт
 
Сообщения: 97
Зарегистрирован: 07 мар 2012, 09:07
Откуда: Нерезиновая
Skype: islamov_denis
  • Сайт

Re: Как определить силу которая воздействует на Rigidbody

Сообщение sindo 23 ноя 2013, 14:21

IDoNotExist писал(а):По идее все должно быть легко и просто "Сила = Масса * Ускорение". То есть, по идее чтобы нам мгновенно остановить движущееся Rigigdbody достаточно этого:...

Тема старая, но все же отвечу может кому пригодится еще. Надеюсь, я правильно понял вопрос и думаю что тут все таки "легко и просто" :)
Как уже сказали "Сила = Масса * Ускорение" (F = m * a) и так как у нас есть только скорость, то пригодится еще одна формула из 7 класса a = V / t.
И немного рассуждений:
Чтобы остановить (заморозить) объект в некоторый момент времени в FixedUpdate нам достаточно приложить силу: противоположную силе тяжести (чтобы объект больше не падал на землю) и плюс силу которая погасит уже имеющую скорость у объекта. т.е. если объект движется со скорость V и нам надо получить нулевую скорость через время равное смене кадра, то получаем ускорение a = V / t, и соответственно применяем противоположную силу F=-a*m.
Надеюсь понятно изложил, вот что мы получаем:
Синтаксис:
Используется csharp
       
Vector3 G = -new Vector3(0,-9.81f,0) * rigidbody.mass; // Сила противоположная силе тяжести g*m
Vector3 F = -rigidbody.velocity/Time.fixedDeltaTime * rigidbody.mass; // Сила которая придает отрицательное ускорение, которое через время fixedDeltaTime приводит скорость к нулевой
rigidbody.AddForce(F+G, ForceMode.Force);   // Применяем силу к объекту
 

В Unity мы можем также прикладывать не силу, а ускорение в результате запись можно сократить:
Синтаксис:
Используется csharp
       
Vector3 Ga = -new Vector3(0,-9.81f,0);
Vector3 Fa = -rigidbody.velocity/Time.fixedDeltaTime;
rigidbody.AddForce(Fa+Ga, ForceMode.Acceleration);   // Применяем ускорение к объекту
 
sindo
UNец
 
Сообщения: 11
Зарегистрирован: 13 авг 2012, 13:04

Re: Как определить силу которая воздействует на Rigidbody

Сообщение sindo 27 ноя 2013, 11:37

IDoNotExist писал(а):Вообщем не парьтесь, мои ковыряния в этом направлении привели к выводу что только на основе данных которое предоставляет нам Rigidbody, вычислить всю силу воздействия на него в текущем кадре невозможно.

Мне кажется Вы просто не до конца понимаете, что такое СИЛА ^:)^ Может стоит перечитать учебник по физики за 7 класс? Когда я сделал это в сознательном возрасте (после университета) многие вещи встали на свои места ;)
В Unity в текущем кадре кроме силы тяжести (если она включена) и drag (если задано замедление) больше ни каких сил не действует на объект, ну и за исключением тех которые вы сами добавляете в FixedUpdate.
Тут главное понимать один факт, что под действием силы объект не движется, а именно УСКОРЯЕТСЯ! Сила это есть ускорение (ну и конечно ее величина еще зависит от массы).
IDoNotExist писал(а):
_Disa_ писал(а):a = (V1-V2)/deltaTime, где V1 скорость в текущем кадре, V2 в прошлом

А как быть если V1 = V2?

В своем сообщении _Disa_ написал как найти силу которая действовала на объект в прошлом кадре. И в случаи V1=V2, мы просто получаем, что ускорение равно 0, т.е. сила на объект не действовала. Если объект движется равномерно без ускорения, то на него и не действует ни какие силы либо сумма этих сил равна нулю. Например, если Вы будете воздействовать на объект силой всего в 1 Ньютон и под действием этой силы объект сдвинется за 1 минуту хотя бы на 1 мм, то это все равно будет означать, что такой силой Вы сможете разогнать объект до любой космической скорости (ну конечно если вы умеете ждать и больше не будет появляться новых сил :D ) . Таким образом получаем, если к объекту приложить силу, то объект начнет ускоряться в этом направлении, если мы уберем силу, то он будет бесконечно двигаться с той скоростью до которой успел ускориться под действием этой силы.
Поэтому в Unity и нет ни каких "менеджеров сил", там в каждом кадре вы сами добавляете силу, которая будет воздействовать на объект до следующего вызова FixedUpdate, если вы ее повторно не приложите, то она и не будет больше действовать на объект. Также не забываем про силы, которые Вы еще задаете в unity и они автоматически прикладываются к объекту, такие как сила притяжение, сила замедления (drag) и сила реакции опоры (при столкновении с коллайдерами).
sindo
UNец
 
Сообщения: 11
Зарегистрирован: 13 авг 2012, 13:04

Re: Как определить силу которая воздействует на Rigidbody

Сообщение IDoNotExist 27 ноя 2013, 17:50

sindo писал(а):
IDoNotExist писал(а):По идее все должно быть легко и просто "Сила = Масса * Ускорение". То есть, по идее чтобы нам мгновенно остановить движущееся Rigigdbody достаточно этого:...

Чтобы остановить (заморозить) объект в некоторый момент времени в FixedUpdate нам достаточно приложить силу: противоположную силе тяжести (чтобы объект больше не падал на землю) и плюс силу которая погасит уже имеющую скорость у объекта. т.е. если объект движется со скорость V и нам надо получить нулевую скорость через время равное смене кадра, то получаем ускорение a = V / t, и соответственно применяем противоположную силу F=-a*m.

Все правильно написали, в этом случае тело остановится, но вопрос был в том, как определить ту самую силу тяжести (мы её не знаем по умолчанию), для того чтобы остановить его полностью, но если при этом мы знаем только данные которые нам предоставляет Rigidbody.

sindo писал(а):
IDoNotExist писал(а):Вообщем не парьтесь, мои ковыряния в этом направлении привели к выводу что только на основе данных которое предоставляет нам Rigidbody, вычислить всю силу воздействия на него в текущем кадре невозможно.

Мне кажется Вы просто не до конца понимаете, что такое СИЛА ^:)^ Может стоит перечитать учебник по физики за 7 класс? Когда я сделал это в сознательном возрасте (после университета) многие вещи встали на свои места ;)
В Unity в текущем кадре кроме силы тяжести (если она включена) и drag (если задано замедление) больше ни каких сил не действует на объект, ну и за исключением тех которые вы сами добавляете в FixedUpdate.
Тут главное понимать один факт, что под действием силы объект не движется, а именно УСКОРЯЕТСЯ! Сила это есть ускорение (ну и конечно ее величина еще зависит от массы).

Ну и где решение проблемы в итоге если вы такой начитанный? Или вы это все написали чтобы быть капитаном очевидностью?
Аватара пользователя
IDoNotExist
Адепт
 
Сообщения: 1432
Зарегистрирован: 23 мар 2011, 09:18
Skype: iamnoexist

Re: Как определить силу которая воздействует на Rigidbody

Сообщение sindo 27 ноя 2013, 20:04

IDoNotExist писал(а):Все правильно написали, в этом случае тело остановится, но вопрос был в том, как определить ту самую силу тяжести (мы её не знаем по умолчанию), для того чтобы остановить его полностью, но если при этом мы знаем только данные которые нам предоставляет Rigidbody.

Почему это мы не знаем силу тяжести?? Мы по умолчанию ее знаем: массу объекта мы сами задаем, как собственно и ускорение свободного падения (Edit -> Project Settings -> Physics). И как сила тяжести связана с "остановить его полностью"? Убрав полностью силу тяжести, тело продолжит равномерное движение вниз. Может Вы все же не внимательно прочитали мои очевидные высказывания? :-\
IDoNotExist писал(а):Ну и где решение проблемы в итоге если вы такой начитанный? Или вы это все написали чтобы быть капитаном очевидностью?

Не хотел Вас ни как обидеть :(
Да, я говорю очевидные вещи, потому что здесь все очевидно :) Я действительно не понимаю, какую информацию и зачем Вы хотите добавить в rigidbody? :(
Мне кажется все что нужно уже имеется в Unity3d. Вы можете еще раз объяснить какая все таки у Вас проблема?
Я могу конечно сильно ошибаться, но мне казалось, что Вы решали задачу типа такой:
Автомобиль движется с постоянной скорость 50 км/ч. Как определить силу, которая действует на автомобиль? Силой тяжести и всяческими силами трения пренебречь.
sindo
UNец
 
Сообщения: 11
Зарегистрирован: 13 авг 2012, 13:04

Re: Как определить силу которая воздействует на Rigidbody

Сообщение sindo 28 ноя 2013, 07:49

IDoNotExist писал(а):Из этой ситуации конечно есть выходы, но в виде всяческих извращений, например можно складировать где нибудь все силы с помощью которых будем манипулировать данным телом, а потом учитывать их при воздействии (а-ля менеджер сил).

Если Вы будете "складировать где нибудь все силы", то Вы все равно не сможете с помощью них "остановить объект полностью". Максимум что Вы сможете это переместить объект в его исходную точку. Т.е. сохраняя все силы, которые действовали на объект, Вы пытаетесь сохранить полностью его хаотичную траекторию движения. Зачем это Вам я не понимаю? Если Вам нужна траектория движения, проще тогда сохранять его позицию.

IDoNotExist писал(а):Можно как выше написали использовать несколько кадров чтобы рассчитать реальное ускорение.

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

IDoNotExist писал(а):Я предполагаю что где то в недрах PhysX это все уже есть, просто к этому нет доступа из [unity 3D].

А мне кажется, что PhysX все же не хранит историю сил, она ему совершенно ни к чему. Он рассчитывает следующую точку положения тела на основе текущей скорости тела и приложенных сил к телу на данной итерации (которые Вы задаете в FixedUpdate и сил которые прикладывает Unity: сила тяжести и т.д.).
:-??
sindo
UNец
 
Сообщения: 11
Зарегистрирован: 13 авг 2012, 13:04


Вернуться в PhysX

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

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