Unity, Rigidbody.MovePosition() не работает, если Transform.position только что измененC#

Место общения программистов C#
Ответить Пред. темаСлед. тема
Anonymous
 Unity, Rigidbody.MovePosition() не работает, если Transform.position только что изменен

Сообщение Anonymous »

Вопрос
Этот код работает. ↓

Код: Выделить всё

private void FixedUpdate()
{
Vector3 newPosition = new Vector3(0, 1, 0);
GetComponent().MovePosition(newPosition);
}
Этот код не работает. ↓

Код: Выделить всё

private void FixedUpdate()
{
Vector3 newPosition = new Vector3(0, 1, 0);

Vector3 oldPosition = transform.position;
transform.position = newPosition;
transform.position = oldPosition;

GetComponent().MovePosition(newPosition);
}
Я тестировал в Unity 2019.4 и 2020.3.
Итак, похоже, что Rigidbody.MovePosition() не будет работать, если только что изменилось Transform.position.
Почему это происходит?

Добавлено 2021.9.3
Я обнаружил, что можно использовать Physics.SyncTransforms() для решения проблемы.
Этот код работает. ↓

Код: Выделить всё

private void FixedUpdate()
{
Vector3 newPosition = new Vector3(0, 1, 0);

Vector3 oldPosition = transform.position;
transform.position = newPosition;
transform.position = oldPosition;

Physics.SyncTransforms();  //newly added

GetComponent().MovePosition(newPosition);
}
Добавлено 2023.9.2
【Part1】
Прошло два года. Сейчас мне снова приходится иметь дело с физикой.
Я узнал, что Rigidbody.position лучше, чем Transform.position, если я хочу изменить положение напрямую.

И При правильном использовании Rigidbody.position не приведет к тому, что Rigidbody.MovePosition() не будет работать.
Как говорит @thekirmizi, перемещение объектов осуществляется как с помощью Transform.position, так и с помощью Rigidbody. MovePosition() далеко от лучшей практики.
Если я хочу переместить объект непрерывным/физическим способом, я могу использовать Rigidbody.velocity , Rigidbody.AddForce или Rigidbody.MovePosition.

Непрерывный/физический способ означает, что объект может столкнуться с другим RigidBody во время движения и затем не будет перемещен в пункт назначения.< /p>
Если я хочу переместить объект телепортирующимся способом, я могу использовать Transform.postion или Rigidbody.position.

By таким образом объект телепортируется (или прыгает) из одного места в другое.
Редко непрерывный способ и способ телепортации сочетаются вместе.
Если я знаком с Unity физической системы, мне следует выбрать один способ, прежде чем программировать.

(Конечно, я не знаком с физической системой 2 года назад, поэтому я пришел к неловкому варианту, который хочу использовать оба способа.)
【Part2】
Наконец, почему изменение Transform.position приводит к тому, что Rigidbody>.MovePosition не работает?

Я не могу быть уверен, но теперь могу кое-что предположить.
Внутреннее обновление физики В ExecutionOrder — это реальное место, где физика (например, физическое перемещение, столкновение и другие).

То есть, если я запущу Rigidbody.MovePosition, твердое тело не будет перемещаться напрямую, оно будет перемещено в обновлении внутренней физики. До обновления внутренней физики объект все еще находится в старой позиции, а после обновления внутренней физики он перемещается в новую позицию.
Думаю, если я запущу Rigidbody.MovePosition(newPosition ), Unity получает от меня команду переместить объект из oldPosition в newPosition. Важны как oldPosition, так и newPosition.

(На самом деле это предположение, не имеющее доказательств. У него есть прекрасная возможность ошибиться. Единственный плюс в том, что оно может помочь мне понять, почему Transform. move несовместимо с Rigidbody.MovePosition.)
В обновлении внутренней физики, когда Unity собирается выполнить Rigidbody.MovePosition, он проверяет, находится ли объект все еще в старой позиции. Приказано переместить его из oldPosition в newPosition. Если он больше не находится в oldPosition, Unity посчитает заказ устаревшим и не выполнит Rigidbody.MovePosition.
Позиции oldPosition и newPosition являются физическими позициями, то есть Rigidbody.position.

Итак, если код Rigidbody.MovePosition выполняется в time1, обновление внутренней физики действительно выполняет Rigidbody.MovePosition в время2. Rigidbody.position должна оставаться неизменной между временем 1 и временем 2.

Итак, Rigidbody.position = oldPosition2; Rigidbody.MovePosition(newPositon); //Обновление внутренней физики — это нормально, потому что Rigidbody.position изменяется раньше Rigidbody.MovePosition, и между временем time1 и time2 изменений не будет.

Но Rigidbody.MovePosition(newPositon); Rigidbody.position = oldPosition2; //Обновление внутренней физики приведет к тому, что MovePosition не будет работать. Rigidbody.position изменяется между временем 1 и временем 2.
Давайте поговорим о Transform.position = oldPosition2; Rigidbody.MovePosition(newPositon); //Обновление внутренней физики.

Код: Выделить всё

Transform.position = oldPosition2
приводит к тому, что Transform.position и Rigidbody.position имеют разные значения, а значение Transform.position является более новым.
Я думаю, что на первом этапе обновления внутренней физики Unity синхронизирует Transform.position и Rigidbody. позиция. Если Transform.position имеет более новое значение, Rigidbody.position будет присвоено более новое значение, которым в примере является oldPosition2.

Затем, когда он собирается выполнить MovePosition, Unity обнаруживает, что Rigidbody.position изменено, поэтому оно не выполняется.

Это означает Transform.position = oldPosition2; Rigidbody.MovePosition(newPositon); //Обновление внутренней физики равно Transform.position = oldPosition2; Rigidbody.MovePosition(newPositon); Rigidbody.position = Transform.position; //Слева от обновления внутренней физики.

Rigidbody.position изменяется между временем 1 и временем 2.

Код: Выделить всё

Transform.position = oldPosition2; Physics.SyncTransforms(); Rigidbody.MovePosition(newPositon);//Internal Physics Update
равно Transform.position = oldPosition2; Rigidbody.position = Transform.position; Rigidbody.MovePosition(newPositon); //Обновление внутренней физики.

Rigidbody.position не имеет изменений между time1 и time2.
Таким образом, Physics.SyncTransforms() может помочь создать Transform.position и Rigidbody.MovePosition совместимо.
В заключение:

Код: Выделить всё

Rigidbody.position = oldPosition2; Rigidbody.MovePosition(newPositon);


Код: Выделить всё

Rigidbody.MovePosition(newPositon); Rigidbody.position = oldPosition2;
❌

Код: Выделить всё

Transform.position = oldPosition2; Rigidbody.MovePosition(newPositon);
❌

Код: Выделить всё

Transform.position = oldPosition2; Physics.SyncTransforms(); Rigidbody.MovePosition(newPositon);


Вот и все. Это мое предположение и мое понимание спустя 2 года. 😄

Подробнее здесь: https://stackoverflow.com/questions/688 ... s-just-cha
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение
  • Unity, Rigidbody.MovePosition() не работает, если Transform.position только что изменен
    Anonymous » » в форуме C#
    0 Ответы
    11 Просмотры
    Последнее сообщение Anonymous
  • Vuetify: justify-position/align-position vs justify="position"/align="position"
    Anonymous » » в форуме CSS
    0 Ответы
    75 Просмотры
    Последнее сообщение Anonymous
  • Почему RigidBody.MovePosition игнорирует столкновения?
    Anonymous » » в форуме C#
    0 Ответы
    33 Просмотры
    Последнее сообщение Anonymous
  • Созданный экземпляр gameObject в Unity не будет обновлять Transform.position.
    Anonymous » » в форуме C#
    0 Ответы
    8 Просмотры
    Последнее сообщение Anonymous
  • Созданный экземпляр gameObject в Unity не будет обновлять Transform.position.
    Anonymous » » в форуме C#
    0 Ответы
    9 Просмотры
    Последнее сообщение Anonymous

Вернуться в «C#»