Как предотвратить прохождение коллайдеров друг через друга?
у меня возникли проблемы с хранением игровых объектов внутри замкнутого пространства. Когда они достигают края, происходит какое-то мгновенное отталкивание, но затем они проходят прямо сквозь стену.
Я использую Box Collider на игроке и сетчатый коллайдер для стены уровня. У меня возникли проблемы с персонажем игрока (космический корабль), что движение контролируется игроком. И с снарядами, которые ведут огонь и забывают двигаться с постоянной скоростью.
это мой код движения для моего игрока. Он работает в
7 ответов
столкновение с быстро движущимися объектами всегда является проблемой. Хороший способ обеспечить обнаружение всех столкновений-использовать Raycasting вместо того, чтобы полагаться на физическую симуляцию. Это хорошо работает для пуль или небольших объектов, но не даст хороших результатов для больших объектов. http://unity3d.com/support/documentation/ScriptReference/Physics.Raycast.html
псевдо-codeish (у меня нет завершения кода здесь и плохой памяти):
void FixedUpdate()
{
Vector3 direction = new Vector3(transform.position - lastPosition);
Ray ray = new Ray(lastPosition, direction);
RaycastHit hit;
if (Physics.Raycast(ray, hit, direction.magnitude))
{
// Do something if hit
}
this.lastPosition = transform.position;
}
У меня есть прототип пинбола, который также дал мне много проблем в тех же областях. Это все шаги, которые я предпринял, чтобы почти (но еще не полностью) решить эти проблемы:
для быстро движущихся объектов:
установите интерполяцию rigidbody в "интерполяцию" (это не влияет на фактическое моделирование физики, но обновляет рендеринг объекта должным образом-используйте это только для важных объектов с точки зрения рендеринга, таких как игрок или пинбол, но не для снарядов)
установите обнаружение столкновений в непрерывное динамическое
прикрепить скрипт DontGoThroughThings (https://www.auto.tuwien.ac.at/wordpress/?p=260) к вашему объекту. Этот скрипт умело использует решение Raycasting, которое я опубликовал в своем другом ответе, чтобы оттянуть оскорбительные объекты до точек столкновения.
на Правка - > Настройки Проекта - > Физика:
установите минимальное проникновение для штрафа до очень низкого значения. Я установил свой 0.001
установите счетчик итераций решателя в более высокое значение. Я установил свой на 50, но вы, вероятно, можете сделать хорошо с гораздо меньшим.
все, что будет иметь штраф в performace, но это неизбежно. Значения по умолчанию мягки по производительности, но на самом деле не предназначены для правильного моделирования небольших и быстро движущихся объекты.
Как насчет установки обнаружения столкновения rigidbody в непрерывно или Непрерывный Динамический?
http://unity3d.com/support/documentation/Components/class-Rigidbody.html
поэтому я не смог заставить коллайдеры сетки работать. Я создал составной коллайдер, используя простые коллайдеры, и он работал точно так, как ожидалось.
другие тесты с простыми коллайдерами сетки вышли то же самое.
похоже, что лучший ответ-построить составной коллайдер из простых коллайдеров коробки/сферы.
для моего конкретного случая я написал мастер, который создает составной коллайдер в форме трубы.
@script AddComponentMenu("Colliders/Pipe Collider");
class WizardCreatePipeCollider extends ScriptableWizard
{
public var outterRadius : float = 200;
public var innerRadius : float = 190;
public var sections : int = 12;
public var height : float = 20;
@MenuItem("GameObject/Colliders/Create Pipe Collider")
static function CreateWizard()
{
ScriptableWizard.DisplayWizard.<WizardCreatePipeCollider>("Create Pipe Collider");
}
public function OnWizardUpdate() {
helpString = "Creates a Pipe Collider";
}
public function OnWizardCreate() {
var theta : float = 360f / sections;
var width : float = outterRadius - innerRadius;
var sectionLength : float = 2 * outterRadius * Mathf.Sin((theta / 2) * Mathf.Deg2Rad);
var container : GameObject = new GameObject("Pipe Collider");
var section : GameObject;
var sectionCollider : GameObject;
var boxCollider : BoxCollider;
for(var i = 0; i < sections; i++)
{
section = new GameObject("Section " + (i + 1));
sectionCollider = new GameObject("SectionCollider " + (i + 1));
section.transform.parent = container.transform;
sectionCollider.transform.parent = section.transform;
section.transform.localPosition = Vector3.zero;
section.transform.localRotation.eulerAngles.y = i * theta;
boxCollider = sectionCollider.AddComponent.<BoxCollider>();
boxCollider.center = Vector3.zero;
boxCollider.size = new Vector3(width, height, sectionLength);
sectionCollider.transform.localPosition = new Vector3(innerRadius + (width / 2), 0, 0);
}
}
}
Изменить - - - > Настройки Проекта - - - > Время ... уменьшите значение "фиксированный шаг времени".. Это решит проблему, но может негативно повлиять на производительность.
другим решением может быть вычисление координат (например, у вас есть мяч и стена. Мяч попадет в стену. Поэтому вычислите координаты стены и установите процесс удара в соответствии с этими кординатами)
1.) Никогда не используйте сетчатый коллайдер. Используйте комбинацию box и capsule collider.
2.) Проверьте ограничения в RigidBody. Если поставить галочку заморозить позицию X, то она пройдет через объект по оси X. (То же самое для оси y).
старый вопрос, но, возможно, это поможет кому-то.
перейдите в настройки проекта > Время и попробуйте разделить фиксированный шаг времени и максимально допустимый шаг времени на два или четыре.
У меня была проблема, что мой игрок смог протиснуться через отверстия меньше, чем игроки коллайдера, и это решило ее. Это также помогает остановить быстро движущиеся объекты.