Как предотвратить коллайдеры от прохождения друг друга?
У меня возникают проблемы с сохранением игровых объектов внутри содержащегося пространства. Когда они достигают края, происходит мгновенное отталкивание назад, но затем они пройдут прямо через стену.
Я использую Box Player на игроком и Mesh Collider для уровня стены. У меня возникают проблемы с персонажем игрока (космическим кораблем), что движение контролируется игроком. И с снарядами, которые стреляют и забывают двигаться с постоянной скоростью.
Это мой код для моего игрока. Он запускается в функции FixedUpdate()
.
//Movement
haxis = Input.GetAxis("Horizontal") * speed;
vaxis = Input.GetAxis("Vertical") * speed;
moveVector.x = haxis;
moveVector.z = vaxis;
if(moveVector.magnitude > 1)
{
moveVector.Normalize();
}
rigidbody.MovePosition(transform.position + moveVector * speed);
С пулями им дается скорость, и двигатель вычисляет их видеоролики. Они используют Box Collider, и он установлен как триггер, поэтому у них нет физики. Но я использую OnTriggerEnter
для их уничтожения.
//Projectiles without physics collisiions
function OnTriggerEnter (other : Collider) {
Destroy(gameObject);
}
Некоторые, но не все пули будут уничтожены при попадании на сетчатую стену коллайдера. Игрок иногда ударяет его и останавливается, но обычно может проталкивать его. Как я могу делать столкновения с работой коллайдера сетки каждый раз?
Ответы
Ответ 1
Столкновение с быстро движущимися объектами всегда является проблемой. Хороший способ обеспечить обнаружение всех столкновений - использовать Raycasting вместо того, чтобы полагаться на физическое моделирование. Это хорошо работает для пуль или небольших объектов, но не дает хороших результатов для больших объектов.
http://unity3d.com/support/documentation/ScriptReference/Physics.Raycast.html
Псевдокодиш (у меня нет завершения кода здесь и плохой памяти):
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;
}
Ответ 2
У меня есть прототип пинбола, который также дал мне много проблем в тех же областях. Это все шаги, которые я предпринял почти (но еще не полностью), чтобы решить эти проблемы:
Для быстро движущихся объектов:
-
Задайте для Interpolate жесткой формы Interpolate (это не влияет на фактическое физическое моделирование, но обновляет рендеринг объекта правильно - используйте это только для важных объектов с точки зрения рендеринга, например, игрока, или пинбол, но не для снарядов)
-
Установить обнаружение столкновений на непрерывный динамический
-
Подключите script DontGoThroughThings (https://www.auto.tuwien.ac.at/wordpress/?p=260) к вашему объекту. Этот script умело использует решение Raycasting, которое я опубликовал в своем другом ответе, чтобы отбросить объекты-нарушители до точек столкновения.
В Изменить → Настройки проекта → Физика:
-
Установите Min Penetration for Penalty на очень низкое значение. Я установил мой 0,001
-
Установите значение "Итерация счетчика" на большее значение. Я установил для меня 50, но вы, вероятно, можете делать нормально с гораздо меньшим.
Все, что будет иметь штраф в исполнении, но это неизбежно. Значения по умолчанию являются мягкими по производительности, но на самом деле не предназначены для правильного моделирования небольших и быстродвижущихся объектов.
Ответ 3
Как установить обнаружение столкновения жесткого тела на Непрерывный или Непрерывный динамический?
http://unity3d.com/support/documentation/Components/class-Rigidbody.html
Ответ 4
Поэтому мне не удалось заставить Mesh Colliders работать. Я создал составной коллайдер, используя простые полевые коллайдеры, и он работал точно так, как ожидалось.
Другие тесты с простыми коллайдерами Mesh выглядят одинаково.
Похоже, лучший ответ - собрать сложный коллайдер из простых коллайдеров box/sphere.
В моем конкретном случае я написал Мастер, который создает трубчатый составной коллайдер.
@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);
}
}
}
Ответ 5
-
Изменить --- > Настройки проекта --- > Время... decrese Значение фиксированной временной отметки. Это решит проблему, но может отрицательно сказаться на производительности.
-
Другим решением может быть вычисление координат (например, у вас есть мяч и стена, мяч попадает в стену, поэтому вычисляйте координаты стены и устанавливайте процесс удара по этим каналам)
Ответ 6
1.) Никогда не используйте MESH COLLIDER. Используйте комбинацию коллайдера с коробкой и капсулой.
2.) Проверьте ограничения в RigidBody. Если вы отметите позицию фиксации X, то она пройдет через объект по оси X. (То же самое для оси y).
Ответ 7
Старый вопрос, но, возможно, это помогает кому-то.
Перейдите к настройкам проектa > Время и попробуйте делить фиксированный временной интервал и максимально допустимый временной интервал на два или четыре.
У меня была проблема с тем, что мой игрок смог сжать отверстия, меньшие, чем игроки-коллайдеры, и это решило. Это также помогает остановить быстро движущиеся объекты.